blob: 96e99b80f74206f989ee19d93b81558e5f2a9965 [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>
10
[email protected]5285d972011-10-18 18:56:3411#include <string>
[email protected]95d88ffe2010-02-04 21:25:3312#include <vector>
[email protected]77848d12008-11-14 00:00:2213
[email protected]2d731a32010-04-29 01:04:0614#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3015#include "base/compiler_specific.h"
[email protected]57999812013-02-24 05:40:5216#include "base/files/file_path.h"
thestigd8df0332014-09-04 06:33:2917#include "base/files/file_util.h"
[email protected]f3da152d2012-06-02 01:00:5718#include "base/json/json_writer.h"
Adam Rice425cf122015-01-19 06:18:2419#include "base/logging.h"
[email protected]3b63f8f42011-03-28 01:54:1520#include "base/memory/scoped_ptr.h"
[email protected]bf828982013-08-14 18:01:4721#include "base/memory/weak_ptr.h"
[email protected]a34f61ee2014-03-18 20:59:4922#include "base/run_loop.h"
[email protected]125ef482013-06-11 18:32:4723#include "base/strings/string_util.h"
[email protected]750b2f3c2013-06-07 18:41:0524#include "base/strings/utf_string_conversions.h"
[email protected]f36a8132011-09-02 18:36:3325#include "base/test/test_file_util.h"
skyostil4891b25b2015-06-11 11:43:4526#include "base/thread_task_runner_handle.h"
[email protected]277d5942010-08-11 21:02:3527#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0728#include "net/base/chunked_upload_data_stream.h"
[email protected]bacff652009-03-31 17:50:3329#include "net/base/completion_callback.h"
mmenkecbc2b712014-10-09 20:29:0730#include "net/base/elements_upload_data_stream.h"
[email protected]58e32bb2013-01-21 18:23:2531#include "net/base/load_timing_info.h"
32#include "net/base/load_timing_info_test_util.h"
Adam Rice425cf122015-01-19 06:18:2433#include "net/base/net_errors.h"
[email protected]ac790b42009-12-02 04:31:3134#include "net/base/request_priority.h"
initial.commit586acc5fe2008-07-26 22:42:5235#include "net/base/test_completion_callback.h"
[email protected]42fdb452012-11-01 12:44:4036#include "net/base/test_data_directory.h"
[email protected]b2d26cfd2012-12-11 10:36:0637#include "net/base/upload_bytes_element_reader.h"
[email protected]d98961652012-09-11 20:27:2138#include "net/base/upload_file_element_reader.h"
[email protected]6e7845ae2013-03-29 21:48:1139#include "net/cert/mock_cert_verifier.h"
[email protected]bc71b8772013-04-10 20:55:1640#include "net/dns/host_cache.h"
[email protected]f2cb3cf2013-03-21 01:40:5341#include "net/dns/mock_host_resolver.h"
[email protected]df41d0d82014-03-13 00:43:2442#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]3c32c5f2010-05-18 15:18:1243#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0044#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2945#include "net/http/http_auth_handler_ntlm.h"
aberentbba302d2015-12-03 10:20:1946#include "net/http/http_auth_scheme.h"
Adam Rice425cf122015-01-19 06:18:2447#include "net/http/http_basic_state.h"
[email protected]0877e3d2009-10-17 22:29:5748#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5249#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5650#include "net/http/http_network_session_peer.h"
Adam Rice425cf122015-01-19 06:18:2451#include "net/http/http_request_headers.h"
[email protected]17291a022011-10-10 07:32:5352#include "net/http/http_server_properties_impl.h"
[email protected]0877e3d2009-10-17 22:29:5753#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3854#include "net/http/http_stream_factory.h"
Adam Rice425cf122015-01-19 06:18:2455#include "net/http/http_stream_parser.h"
[email protected]c41737d2014-05-14 07:47:1956#include "net/http/http_transaction_test_util.h"
eroman87c53d62015-04-02 06:51:0757#include "net/log/net_log.h"
vishal.b62985ca92015-04-17 08:45:5158#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4659#include "net/log/test_net_log_entry.h"
60#include "net/log/test_net_log_util.h"
sammc5dd160c2015-04-02 02:43:1361#include "net/proxy/mock_proxy_resolver.h"
[email protected]51fff29d2008-12-19 22:17:5362#include "net/proxy/proxy_config_service_fixed.h"
[email protected]e86839fd2013-08-14 18:29:0363#include "net/proxy/proxy_info.h"
[email protected]631f1322010-04-30 17:59:1164#include "net/proxy/proxy_resolver.h"
65#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4466#include "net/socket/client_socket_factory.h"
[email protected]483fa202013-05-14 01:07:0367#include "net/socket/client_socket_pool_manager.h"
ttuttle1f2d7e92015-04-28 16:17:4768#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0269#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0770#include "net/socket/next_proto.h"
[email protected]f7984fc62009-06-22 23:26:4471#include "net/socket/socket_test_util.h"
72#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5473#include "net/spdy/spdy_framer.h"
74#include "net/spdy/spdy_session.h"
75#include "net/spdy/spdy_session_pool.h"
[email protected]23e482282013-06-14 16:08:0276#include "net/spdy/spdy_test_util_common.h"
[email protected]536fd0b2013-03-14 17:41:5777#include "net/ssl/ssl_cert_request_info.h"
[email protected]e86839fd2013-08-14 18:29:0378#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:5779#include "net/ssl/ssl_config_service_defaults.h"
80#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:5481#include "net/ssl/ssl_private_key.h"
[email protected]6e7845ae2013-03-29 21:48:1182#include "net/test/cert_test_util.h"
[email protected]831e4a32013-11-14 02:14:4483#include "net/websockets/websocket_handshake_stream_base.h"
bncf4588402015-11-24 13:33:1884#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:5285#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1586#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:2787#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:5288
[email protected]ad65a3e2013-12-25 18:18:0189using base::ASCIIToUTF16;
90
initial.commit586acc5fe2008-07-26 22:42:5291//-----------------------------------------------------------------------------
92
ttuttle859dc7a2015-04-23 19:42:2993namespace net {
94
[email protected]13c8a092010-07-29 06:15:4495namespace {
96
rdsmithebb50aa2015-11-12 03:44:3897enum TestCase {
98 // Test using the SPDY/3.1 protocol.
99 kTestCaseSPDY31,
100
101 // Test using the HTTP/2 protocol, without specifying a stream
102 // dependency based on the RequestPriority.
103 kTestCaseHTTP2NoPriorityDependencies,
104
105 // Test using the HTTP/2 protocol, specifying a stream
106 // dependency based on the RequestPriority.
107 kTestCaseHTTP2PriorityDependencies
108};
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
ttuttle859dc7a2015-04-23 19:42:29123int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
124 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
125 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02126}
127
ttuttle859dc7a2015-04-23 19:42:29128int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession* session) {
129 return session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
130 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02131}
132
ttuttle859dc7a2015-04-23 19:42:29133bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
134 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
135 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52136}
137
[email protected]f3da152d2012-06-02 01:00:57138// Takes in a Value created from a NetLogHttpResponseParameter, and returns
139// a JSONified list of headers as a single string. Uses single quotes instead
140// of double quotes for easier comparison. Returns false on failure.
[email protected]ea5ef4c2013-06-13 22:50:27141bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
[email protected]f3da152d2012-06-02 01:00:57142 if (!params)
143 return false;
[email protected]ea5ef4c2013-06-13 22:50:27144 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:57145 if (!params->GetList("headers", &header_list))
146 return false;
147 std::string double_quote_headers;
estade8d046462015-05-16 01:02:34148 base::JSONWriter::Write(*header_list, &double_quote_headers);
[email protected]466c9862013-12-03 22:05:28149 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
[email protected]f3da152d2012-06-02 01:00:57150 return true;
151}
152
[email protected]029c83b62013-01-24 05:28:20153// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
154// used.
ttuttle859dc7a2015-04-23 19:42:29155void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20156 EXPECT_TRUE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29157 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25158
[email protected]029c83b62013-01-24 05:28:20159 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
160 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
161
ttuttle859dc7a2015-04-23 19:42:29162 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20163 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25164
165 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25166
[email protected]3b23a222013-05-15 21:33:25167 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25168 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
169 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25170 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25171}
172
[email protected]029c83b62013-01-24 05:28:20173// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
174// used.
ttuttle859dc7a2015-04-23 19:42:29175void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25176 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20177 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29178 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20179
180 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
181 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
182
ttuttle859dc7a2015-04-23 19:42:29183 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
184 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20185 EXPECT_LE(load_timing_info.connect_timing.connect_end,
186 load_timing_info.send_start);
187
188 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20189
[email protected]3b23a222013-05-15 21:33:25190 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20191 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
192 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25193 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20194}
195
196// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
197// used.
ttuttle859dc7a2015-04-23 19:42:29198void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20199 EXPECT_TRUE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29200 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20201
ttuttle859dc7a2015-04-23 19:42:29202 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20203
204 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
205 EXPECT_LE(load_timing_info.proxy_resolve_start,
206 load_timing_info.proxy_resolve_end);
207 EXPECT_LE(load_timing_info.proxy_resolve_end,
208 load_timing_info.send_start);
209 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20210
[email protected]3b23a222013-05-15 21:33:25211 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20212 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
213 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25214 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20215}
216
217// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
218// used.
ttuttle859dc7a2015-04-23 19:42:29219void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20220 int connect_timing_flags) {
221 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29222 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20223
224 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
225 EXPECT_LE(load_timing_info.proxy_resolve_start,
226 load_timing_info.proxy_resolve_end);
227 EXPECT_LE(load_timing_info.proxy_resolve_end,
228 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29229 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
230 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20231 EXPECT_LE(load_timing_info.connect_timing.connect_end,
232 load_timing_info.send_start);
233
234 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20235
[email protected]3b23a222013-05-15 21:33:25236 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20237 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
238 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25239 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25240}
241
ttuttle859dc7a2015-04-23 19:42:29242void AddWebSocketHeaders(HttpRequestHeaders* headers) {
Adam Rice425cf122015-01-19 06:18:24243 headers->SetHeader("Connection", "Upgrade");
244 headers->SetHeader("Upgrade", "websocket");
bncce36dca22015-04-21 22:11:23245 headers->SetHeader("Origin", "http://www.example.org");
Adam Rice425cf122015-01-19 06:18:24246 headers->SetHeader("Sec-WebSocket-Version", "13");
247 headers->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
248}
249
mmenkee65e7af2015-10-13 17:16:42250scoped_ptr<HttpNetworkSession> CreateSession(
251 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34252 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14253}
254
[email protected]448d4ca52012-03-04 04:12:23255} // namespace
256
[email protected]23e482282013-06-14 16:08:02257class HttpNetworkTransactionTest
258 : public PlatformTest,
rdsmithebb50aa2015-11-12 03:44:38259 public ::testing::WithParamInterface<TestCase> {
[email protected]483fa202013-05-14 01:07:03260 public:
[email protected]23e482282013-06-14 16:08:02261 virtual ~HttpNetworkTransactionTest() {
[email protected]483fa202013-05-14 01:07:03262 // Important to restore the per-pool limit first, since the pool limit must
263 // always be greater than group limit, and the tests reduce both limits.
264 ClientSocketPoolManager::set_max_sockets_per_pool(
265 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
266 ClientSocketPoolManager::set_max_sockets_per_group(
267 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
rdsmithebb50aa2015-11-12 03:44:38268 SpdySession::SetPriorityDependencyDefaultForTesting(false);
[email protected]483fa202013-05-14 01:07:03269 }
270
[email protected]e3ceb682011-06-28 23:55:46271 protected:
[email protected]23e482282013-06-14 16:08:02272 HttpNetworkTransactionTest()
rdsmithebb50aa2015-11-12 03:44:38273 : spdy_util_(GetProtocol(), GetDependenciesFromPriority()),
274 session_deps_(GetProtocol()),
[email protected]483fa202013-05-14 01:07:03275 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
276 HttpNetworkSession::NORMAL_SOCKET_POOL)),
277 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
278 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
rdsmithebb50aa2015-11-12 03:44:38279 SpdySession::SetPriorityDependencyDefaultForTesting(
280 GetDependenciesFromPriority());
[email protected]483fa202013-05-14 01:07:03281 }
[email protected]bb88e1d32013-05-03 23:11:07282
[email protected]e3ceb682011-06-28 23:55:46283 struct SimpleGetHelperResult {
284 int rv;
285 std::string status_line;
286 std::string response_data;
sclittlefb249892015-09-10 21:33:22287 int64_t total_received_bytes;
288 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25289 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47290 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59291 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46292 };
293
dcheng67be2b1f2014-10-27 21:47:29294 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50295 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34296 base::MessageLoop::current()->RunUntilIdle();
[email protected]2ff8b312010-04-26 22:20:54297 }
298
dcheng67be2b1f2014-10-27 21:47:29299 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50300 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34301 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09302 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:34303 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09304 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50305 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34306 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09307 }
308
rdsmithebb50aa2015-11-12 03:44:38309 NextProto GetProtocol() const {
310 return GetParam() == kTestCaseSPDY31 ? kProtoSPDY31 : kProtoHTTP2;
311 }
312
313 bool GetDependenciesFromPriority() const {
314 return GetParam() == kTestCaseHTTP2PriorityDependencies;
315 }
316
bnc33b8cef42014-11-19 17:30:38317 const char* GetAlternateProtocolFromParam() {
rdsmithebb50aa2015-11-12 03:44:38318 return AlternateProtocolToString(
319 AlternateProtocolFromNextProto(GetProtocol()));
bnc33b8cef42014-11-19 17:30:38320 }
321
bncc958faa2015-07-31 18:14:52322 std::string GetAlternativeServiceHttpHeader() {
323 return std::string("Alt-Svc: ") + GetAlternateProtocolFromParam() +
324 "=\"www.example.com:443\"\r\n";
325 }
326
[email protected]8a0fc822013-06-27 20:52:43327 std::string GetAlternateProtocolHttpHeader() {
bnc33b8cef42014-11-19 17:30:38328 return std::string("Alternate-Protocol: 443:") +
bncc958faa2015-07-31 18:14:52329 GetAlternateProtocolFromParam() + "\r\n";
[email protected]8a0fc822013-06-27 20:52:43330 }
331
[email protected]202965992011-12-07 23:04:51332 // Either |write_failure| specifies a write failure or |read_failure|
333 // specifies a read failure when using a reused socket. In either case, the
334 // failure should cause the network transaction to resend the request, and the
335 // other argument should be NULL.
336 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
337 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52338
[email protected]a34f61ee2014-03-18 20:59:49339 // Either |write_failure| specifies a write failure or |read_failure|
340 // specifies a read failure when using a reused socket. In either case, the
341 // failure should cause the network transaction to resend the request, and the
342 // other argument should be NULL.
343 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10344 const MockRead* read_failure,
345 bool use_spdy);
[email protected]a34f61ee2014-03-18 20:59:49346
[email protected]5a60c8b2011-10-19 20:14:29347 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
348 size_t data_count) {
[email protected]ff007e162009-05-23 09:13:15349 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52350
[email protected]ff007e162009-05-23 09:13:15351 HttpRequestInfo request;
352 request.method = "GET";
bncce36dca22015-04-21 22:11:23353 request.url = GURL("http://www.example.org/");
[email protected]ff007e162009-05-23 09:13:15354 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52355
vishal.b62985ca92015-04-17 08:45:51356 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07357 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:42358 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:27359 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:41360 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:27361
[email protected]5a60c8b2011-10-19 20:14:29362 for (size_t i = 0; i < data_count; ++i) {
[email protected]bb88e1d32013-05-03 23:11:07363 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
[email protected]5a60c8b2011-10-19 20:14:29364 }
initial.commit586acc5fe2008-07-26 22:42:52365
[email protected]49639fa2011-12-20 23:22:41366 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52367
eroman24bc6a12015-05-06 19:55:48368 EXPECT_TRUE(log.bound().IsCapturing());
[email protected]49639fa2011-12-20 23:22:41369 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]ff007e162009-05-23 09:13:15370 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52371
[email protected]ff007e162009-05-23 09:13:15372 out.rv = callback.WaitForResult();
sclittlefb249892015-09-10 21:33:22373 out.total_received_bytes = trans->GetTotalReceivedBytes();
374 out.total_sent_bytes = trans->GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25375
376 // Even in the failure cases that use this function, connections are always
377 // successfully established before the error.
378 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
379 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
380
[email protected]ff007e162009-05-23 09:13:15381 if (out.rv != OK)
382 return out;
383
384 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50385 // Can't use ASSERT_* inside helper functions like this, so
386 // return an error.
[email protected]90499482013-06-01 00:39:50387 if (response == NULL || response->headers.get() == NULL) {
[email protected]fe2255a2011-09-20 19:37:50388 out.rv = ERR_UNEXPECTED;
389 return out;
390 }
[email protected]ff007e162009-05-23 09:13:15391 out.status_line = response->headers->GetStatusLine();
392
[email protected]80a09a82012-11-16 17:40:06393 EXPECT_EQ("127.0.0.1", response->socket_address.host());
394 EXPECT_EQ(80, response->socket_address.port());
[email protected]6d81b482011-02-22 19:47:19395
ttuttled9dbc652015-09-29 20:00:59396 bool got_endpoint =
397 trans->GetRemoteEndpoint(&out.remote_endpoint_after_start);
398 EXPECT_EQ(got_endpoint,
399 out.remote_endpoint_after_start.address().size() > 0);
400
[email protected]ff007e162009-05-23 09:13:15401 rv = ReadTransaction(trans.get(), &out.response_data);
402 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40403
mmenke43758e62015-05-04 21:09:46404 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:40405 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39406 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40407 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12408 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39409 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40410 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39411 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
412 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15413
[email protected]f3da152d2012-06-02 01:00:57414 std::string line;
415 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
416 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
417
[email protected]79e1fd62013-06-20 06:50:04418 HttpRequestHeaders request_headers;
419 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
420 std::string value;
421 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
bncce36dca22015-04-21 22:11:23422 EXPECT_EQ("www.example.org", value);
[email protected]79e1fd62013-06-20 06:50:04423 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
424 EXPECT_EQ("keep-alive", value);
425
426 std::string response_headers;
427 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
bncce36dca22015-04-21 22:11:23428 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
[email protected]79e1fd62013-06-20 06:50:04429 response_headers);
[email protected]3deb9a52010-11-11 00:24:40430
sclittlefb249892015-09-10 21:33:22431 out.total_received_bytes = trans->GetTotalReceivedBytes();
432 // The total number of sent bytes should not have changed.
433 EXPECT_EQ(out.total_sent_bytes, trans->GetTotalSentBytes());
434
ttuttle1f2d7e92015-04-28 16:17:47435 trans->GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47436 return out;
[email protected]ff007e162009-05-23 09:13:15437 }
initial.commit586acc5fe2008-07-26 22:42:52438
[email protected]5a60c8b2011-10-19 20:14:29439 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
440 size_t reads_count) {
sclittlefb249892015-09-10 21:33:22441 MockWrite data_writes[] = {
442 MockWrite("GET / HTTP/1.1\r\n"
443 "Host: www.example.org\r\n"
444 "Connection: keep-alive\r\n\r\n"),
445 };
[email protected]5a60c8b2011-10-19 20:14:29446
sclittlefb249892015-09-10 21:33:22447 StaticSocketDataProvider reads(data_reads, reads_count, data_writes,
448 arraysize(data_writes));
449 StaticSocketDataProvider* data[] = {&reads};
450 SimpleGetHelperResult out = SimpleGetHelperForData(data, 1);
451
452 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
453 out.total_sent_bytes);
454 return out;
[email protected]b8015c42013-12-24 15:18:19455 }
456
[email protected]ff007e162009-05-23 09:13:15457 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
458 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52459
[email protected]ff007e162009-05-23 09:13:15460 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07461
462 void BypassHostCacheOnRefreshHelper(int load_flags);
463
464 void CheckErrorIsPassedBack(int error, IoMode mode);
465
[email protected]4bd46222013-05-14 19:32:23466 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07467 SpdySessionDependencies session_deps_;
[email protected]483fa202013-05-14 01:07:03468
469 // Original socket limits. Some tests set these. Safest to always restore
470 // them once each test has been run.
471 int old_max_group_sockets_;
472 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15473};
[email protected]231d5a32008-09-13 00:45:27474
rdsmithebb50aa2015-11-12 03:44:38475INSTANTIATE_TEST_CASE_P(ProtoPlusDepend,
bnc57685ae62015-03-10 21:27:20476 HttpNetworkTransactionTest,
rdsmithebb50aa2015-11-12 03:44:38477 testing::Values(kTestCaseSPDY31,
478 kTestCaseHTTP2NoPriorityDependencies,
479 kTestCaseHTTP2PriorityDependencies));
[email protected]23e482282013-06-14 16:08:02480
[email protected]448d4ca52012-03-04 04:12:23481namespace {
482
[email protected]1826a402014-01-08 15:40:48483class BeforeNetworkStartHandler {
484 public:
485 explicit BeforeNetworkStartHandler(bool defer)
486 : defer_on_before_network_start_(defer),
487 observed_before_network_start_(false) {}
488
489 void OnBeforeNetworkStart(bool* defer) {
490 *defer = defer_on_before_network_start_;
491 observed_before_network_start_ = true;
492 }
493
494 bool observed_before_network_start() const {
495 return observed_before_network_start_;
496 }
497
498 private:
499 const bool defer_on_before_network_start_;
500 bool observed_before_network_start_;
501
502 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
503};
504
[email protected]597a1ab2014-06-26 08:12:27505class BeforeProxyHeadersSentHandler {
506 public:
507 BeforeProxyHeadersSentHandler()
508 : observed_before_proxy_headers_sent_(false) {}
509
[email protected]1252d42f2014-07-01 21:20:20510 void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
511 HttpRequestHeaders* request_headers) {
[email protected]597a1ab2014-06-26 08:12:27512 observed_before_proxy_headers_sent_ = true;
513 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
514 }
515
516 bool observed_before_proxy_headers_sent() const {
517 return observed_before_proxy_headers_sent_;
518 }
519
520 std::string observed_proxy_server_uri() const {
521 return observed_proxy_server_uri_;
522 }
523
524 private:
525 bool observed_before_proxy_headers_sent_;
526 std::string observed_proxy_server_uri_;
527
528 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler);
529};
530
[email protected]15a5ccf82008-10-23 19:57:43531// Fill |str| with a long header list that consumes >= |size| bytes.
532void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51533 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19534 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
535 const int sizeof_row = strlen(row);
536 const int num_rows = static_cast<int>(
537 ceil(static_cast<float>(size) / sizeof_row));
538 const int sizeof_data = num_rows * sizeof_row;
539 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43540 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51541
[email protected]4ddaf2502008-10-23 18:26:19542 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43543 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19544}
545
thakis84dff942015-07-28 20:47:38546#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29547// Alternative functions that eliminate randomness and dependency on the local
548// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20549void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29550 static const uint8 bytes[] = {
551 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
552 };
553 static size_t current_byte = 0;
554 for (size_t i = 0; i < n; ++i) {
555 output[i] = bytes[current_byte++];
556 current_byte %= arraysize(bytes);
557 }
558}
559
[email protected]fe2bc6a2009-03-23 16:52:20560void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29561 static const uint8 bytes[] = {
562 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
563 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
564 };
565 static size_t current_byte = 0;
566 for (size_t i = 0; i < n; ++i) {
567 output[i] = bytes[current_byte++];
568 current_byte %= arraysize(bytes);
569 }
570}
571
[email protected]fe2bc6a2009-03-23 16:52:20572std::string MockGetHostName() {
573 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29574}
thakis84dff942015-07-28 20:47:38575#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29576
[email protected]e60e47a2010-07-14 03:37:18577template<typename ParentPool>
578class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31579 public:
[email protected]9e1bdd32011-02-03 21:48:34580 CaptureGroupNameSocketPool(HostResolver* host_resolver,
581 CertVerifier* cert_verifier);
[email protected]e60e47a2010-07-14 03:37:18582
[email protected]d80a4322009-08-14 07:07:49583 const std::string last_group_name_received() const {
584 return last_group_name_;
585 }
586
dmichaeld6e570d2014-12-18 22:30:57587 int RequestSocket(const std::string& group_name,
588 const void* socket_params,
589 RequestPriority priority,
590 ClientSocketHandle* handle,
591 const CompletionCallback& callback,
592 const BoundNetLog& net_log) override {
[email protected]04e5be32009-06-26 20:00:31593 last_group_name_ = group_name;
594 return ERR_IO_PENDING;
595 }
dmichaeld6e570d2014-12-18 22:30:57596 void CancelRequest(const std::string& group_name,
597 ClientSocketHandle* handle) override {}
598 void ReleaseSocket(const std::string& group_name,
599 scoped_ptr<StreamSocket> socket,
600 int id) override {}
601 void CloseIdleSockets() override {}
602 int IdleSocketCount() const override { return 0; }
603 int IdleSocketCountInGroup(const std::string& group_name) const override {
[email protected]04e5be32009-06-26 20:00:31604 return 0;
605 }
dmichaeld6e570d2014-12-18 22:30:57606 LoadState GetLoadState(const std::string& group_name,
607 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31608 return LOAD_STATE_IDLE;
609 }
dmichaeld6e570d2014-12-18 22:30:57610 base::TimeDelta ConnectionTimeout() const override {
[email protected]a796bcec2010-03-22 17:17:26611 return base::TimeDelta();
612 }
[email protected]d80a4322009-08-14 07:07:49613
614 private:
[email protected]04e5be32009-06-26 20:00:31615 std::string last_group_name_;
616};
617
[email protected]ab739042011-04-07 15:22:28618typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
619CaptureGroupNameTransportSocketPool;
[email protected]e772db3f2010-07-12 18:11:13620typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
621CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06622typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11623CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18624typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
625CaptureGroupNameSSLSocketPool;
626
rkaplowd90695c2015-03-25 22:12:41627template <typename ParentPool>
[email protected]e60e47a2010-07-14 03:37:18628CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34629 HostResolver* host_resolver,
630 CertVerifier* /* cert_verifier */)
rkaplowd90695c2015-03-25 22:12:41631 : ParentPool(0, 0, host_resolver, NULL, NULL) {
632}
[email protected]e60e47a2010-07-14 03:37:18633
hashimoto0d3e4fb2015-01-09 05:02:50634template <>
[email protected]2df19bb2010-08-25 20:13:46635CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
hashimotodae13b02015-01-15 04:28:21636 HostResolver* /* host_resolver */,
[email protected]9e1bdd32011-02-03 21:48:34637 CertVerifier* /* cert_verifier */)
rkaplowd90695c2015-03-25 22:12:41638 : HttpProxyClientSocketPool(0, 0, NULL, NULL, NULL) {
hashimoto0d3e4fb2015-01-09 05:02:50639}
[email protected]2df19bb2010-08-25 20:13:46640
[email protected]007b3f82013-04-09 08:46:45641template <>
[email protected]e60e47a2010-07-14 03:37:18642CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
hashimotodae13b02015-01-15 04:28:21643 HostResolver* /* host_resolver */,
[email protected]9e1bdd32011-02-03 21:48:34644 CertVerifier* cert_verifier)
[email protected]007b3f82013-04-09 08:46:45645 : SSLClientSocketPool(0,
646 0,
[email protected]007b3f82013-04-09 08:46:45647 cert_verifier,
648 NULL,
649 NULL,
[email protected]284303b62013-11-28 15:11:54650 NULL,
eranm6571b2b2014-12-03 15:53:23651 NULL,
[email protected]007b3f82013-04-09 08:46:45652 std::string(),
653 NULL,
654 NULL,
655 NULL,
656 NULL,
657 NULL,
[email protected]8e458552014-08-05 00:02:15658 NULL) {
659}
[email protected]2227c692010-05-04 15:36:11660
[email protected]231d5a32008-09-13 00:45:27661//-----------------------------------------------------------------------------
662
[email protected]79cb5c12011-09-12 13:12:04663// Helper functions for validating that AuthChallengeInfo's are correctly
664// configured for common cases.
665bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
666 if (!auth_challenge)
667 return false;
668 EXPECT_FALSE(auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:23669 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:04670 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19671 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04672 return true;
673}
674
675bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
676 if (!auth_challenge)
677 return false;
678 EXPECT_TRUE(auth_challenge->is_proxy);
679 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
680 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19681 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04682 return true;
683}
684
685bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
686 if (!auth_challenge)
687 return false;
688 EXPECT_FALSE(auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:23689 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:04690 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19691 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04692 return true;
693}
694
thakis84dff942015-07-28 20:47:38695#if defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04696bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
697 if (!auth_challenge)
698 return false;
699 EXPECT_FALSE(auth_challenge->is_proxy);
700 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
701 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19702 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04703 return true;
704}
thakis84dff942015-07-28 20:47:38705#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04706
[email protected]448d4ca52012-03-04 04:12:23707} // namespace
708
[email protected]23e482282013-06-14 16:08:02709TEST_P(HttpNetworkTransactionTest, Basic) {
mmenkee65e7af2015-10-13 17:16:42710 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:40711 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:41712 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]231d5a32008-09-13 00:45:27713}
714
[email protected]23e482282013-06-14 16:08:02715TEST_P(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27716 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35717 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
718 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06719 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27720 };
[email protected]31a2bfe2010-02-09 08:03:39721 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
722 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42723 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27724 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
725 EXPECT_EQ("hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22726 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
727 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47728 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59729
730 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27731}
732
733// Response with no status line.
[email protected]23e482282013-06-14 16:08:02734TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27735 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35736 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06737 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27738 };
[email protected]31a2bfe2010-02-09 08:03:39739 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
740 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42741 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27742 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
743 EXPECT_EQ("hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22744 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
745 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27746}
747
748// Allow up to 4 bytes of junk to precede status line.
[email protected]23e482282013-06-14 16:08:02749TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27750 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35751 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06752 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27753 };
[email protected]31a2bfe2010-02-09 08:03:39754 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
755 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42756 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27757 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
758 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22759 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
760 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27761}
762
763// Allow up to 4 bytes of junk to precede status line.
[email protected]23e482282013-06-14 16:08:02764TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27765 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35766 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06767 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27768 };
[email protected]31a2bfe2010-02-09 08:03:39769 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
770 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42771 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27772 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
773 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22774 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
775 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27776}
777
778// Beyond 4 bytes of slop and it should fail to find a status line.
[email protected]23e482282013-06-14 16:08:02779TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27780 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35781 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06782 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27783 };
[email protected]31a2bfe2010-02-09 08:03:39784 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
785 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42786 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25787 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
788 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
sclittlefb249892015-09-10 21:33:22789 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
790 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27791}
792
793// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
[email protected]23e482282013-06-14 16:08:02794TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27795 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35796 MockRead("\n"),
797 MockRead("\n"),
798 MockRead("Q"),
799 MockRead("J"),
800 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06801 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27802 };
[email protected]31a2bfe2010-02-09 08:03:39803 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
804 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42805 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27806 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
807 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22808 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
809 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27810}
811
812// Close the connection before enough bytes to have a status line.
[email protected]23e482282013-06-14 16:08:02813TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27814 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35815 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06816 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27817 };
[email protected]31a2bfe2010-02-09 08:03:39818 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
819 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42820 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27821 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
822 EXPECT_EQ("HTT", out.response_data);
sclittlefb249892015-09-10 21:33:22823 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
824 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:52825}
826
[email protected]f9d44aa2008-09-23 23:57:17827// Simulate a 204 response, lacking a Content-Length header, sent over a
828// persistent connection. The response should still terminate since a 204
829// cannot have a response body.
[email protected]23e482282013-06-14 16:08:02830TEST_P(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:19831 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:17832 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35833 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:19834 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:06835 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:17836 };
[email protected]31a2bfe2010-02-09 08:03:39837 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
838 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42839 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17840 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
841 EXPECT_EQ("", out.response_data);
sclittlefb249892015-09-10 21:33:22842 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
843 int64_t response_size = reads_size - strlen(junk);
844 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:17845}
846
[email protected]0877e3d2009-10-17 22:29:57847// A simple request using chunked encoding with some extra data after.
[email protected]23e482282013-06-14 16:08:02848TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:19849 std::string final_chunk = "0\r\n\r\n";
850 std::string extra_data = "HTTP/1.1 200 OK\r\n";
851 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:57852 MockRead data_reads[] = {
853 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
854 MockRead("5\r\nHello\r\n"),
855 MockRead("1\r\n"),
856 MockRead(" \r\n"),
857 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:19858 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:06859 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:57860 };
[email protected]31a2bfe2010-02-09 08:03:39861 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
862 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57863 EXPECT_EQ(OK, out.rv);
864 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
865 EXPECT_EQ("Hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22866 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
867 int64_t response_size = reads_size - extra_data.size();
868 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:57869}
870
[email protected]9fe44f52010-09-23 18:36:00871// Next tests deal with http://crbug.com/56344.
872
[email protected]23e482282013-06-14 16:08:02873TEST_P(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00874 MultipleContentLengthHeadersNoTransferEncoding) {
875 MockRead data_reads[] = {
876 MockRead("HTTP/1.1 200 OK\r\n"),
877 MockRead("Content-Length: 10\r\n"),
878 MockRead("Content-Length: 5\r\n\r\n"),
879 };
880 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
881 arraysize(data_reads));
882 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
883}
884
[email protected]23e482282013-06-14 16:08:02885TEST_P(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04886 DuplicateContentLengthHeadersNoTransferEncoding) {
887 MockRead data_reads[] = {
888 MockRead("HTTP/1.1 200 OK\r\n"),
889 MockRead("Content-Length: 5\r\n"),
890 MockRead("Content-Length: 5\r\n\r\n"),
891 MockRead("Hello"),
892 };
893 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
894 arraysize(data_reads));
895 EXPECT_EQ(OK, out.rv);
896 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
897 EXPECT_EQ("Hello", out.response_data);
898}
899
[email protected]23e482282013-06-14 16:08:02900TEST_P(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04901 ComplexContentLengthHeadersNoTransferEncoding) {
902 // More than 2 dupes.
903 {
904 MockRead data_reads[] = {
905 MockRead("HTTP/1.1 200 OK\r\n"),
906 MockRead("Content-Length: 5\r\n"),
907 MockRead("Content-Length: 5\r\n"),
908 MockRead("Content-Length: 5\r\n\r\n"),
909 MockRead("Hello"),
910 };
911 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
912 arraysize(data_reads));
913 EXPECT_EQ(OK, out.rv);
914 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
915 EXPECT_EQ("Hello", out.response_data);
916 }
917 // HTTP/1.0
918 {
919 MockRead data_reads[] = {
920 MockRead("HTTP/1.0 200 OK\r\n"),
921 MockRead("Content-Length: 5\r\n"),
922 MockRead("Content-Length: 5\r\n"),
923 MockRead("Content-Length: 5\r\n\r\n"),
924 MockRead("Hello"),
925 };
926 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
927 arraysize(data_reads));
928 EXPECT_EQ(OK, out.rv);
929 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
930 EXPECT_EQ("Hello", out.response_data);
931 }
932 // 2 dupes and one mismatched.
933 {
934 MockRead data_reads[] = {
935 MockRead("HTTP/1.1 200 OK\r\n"),
936 MockRead("Content-Length: 10\r\n"),
937 MockRead("Content-Length: 10\r\n"),
938 MockRead("Content-Length: 5\r\n\r\n"),
939 };
940 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
941 arraysize(data_reads));
942 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
943 }
944}
945
[email protected]23e482282013-06-14 16:08:02946TEST_P(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00947 MultipleContentLengthHeadersTransferEncoding) {
948 MockRead data_reads[] = {
949 MockRead("HTTP/1.1 200 OK\r\n"),
950 MockRead("Content-Length: 666\r\n"),
951 MockRead("Content-Length: 1337\r\n"),
952 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
953 MockRead("5\r\nHello\r\n"),
954 MockRead("1\r\n"),
955 MockRead(" \r\n"),
956 MockRead("5\r\nworld\r\n"),
957 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:06958 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:00959 };
960 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
961 arraysize(data_reads));
962 EXPECT_EQ(OK, out.rv);
963 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
964 EXPECT_EQ("Hello world", out.response_data);
965}
966
[email protected]1628fe92011-10-04 23:04:55967// Next tests deal with http://crbug.com/98895.
968
969// Checks that a single Content-Disposition header results in no error.
[email protected]23e482282013-06-14 16:08:02970TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:55971 MockRead data_reads[] = {
972 MockRead("HTTP/1.1 200 OK\r\n"),
973 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
974 MockRead("Content-Length: 5\r\n\r\n"),
975 MockRead("Hello"),
976 };
977 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
978 arraysize(data_reads));
979 EXPECT_EQ(OK, out.rv);
980 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
981 EXPECT_EQ("Hello", out.response_data);
982}
983
[email protected]54a9c6e52012-03-21 20:10:59984// Checks that two identical Content-Disposition headers result in no error.
[email protected]23e482282013-06-14 16:08:02985TEST_P(HttpNetworkTransactionTest,
[email protected]54a9c6e52012-03-21 20:10:59986 TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:55987 MockRead data_reads[] = {
988 MockRead("HTTP/1.1 200 OK\r\n"),
989 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
990 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
991 MockRead("Content-Length: 5\r\n\r\n"),
992 MockRead("Hello"),
993 };
994 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
995 arraysize(data_reads));
[email protected]54a9c6e52012-03-21 20:10:59996 EXPECT_EQ(OK, out.rv);
997 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
998 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:55999}
1000
1001// Checks that two distinct Content-Disposition headers result in an error.
[email protected]23e482282013-06-14 16:08:021002TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551003 MockRead data_reads[] = {
1004 MockRead("HTTP/1.1 200 OK\r\n"),
1005 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1006 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1007 MockRead("Content-Length: 5\r\n\r\n"),
1008 MockRead("Hello"),
1009 };
1010 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1011 arraysize(data_reads));
1012 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
1013}
1014
[email protected]54a9c6e52012-03-21 20:10:591015// Checks that two identical Location headers result in no error.
1016// Also tests Location header behavior.
[email protected]23e482282013-06-14 16:08:021017TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551018 MockRead data_reads[] = {
1019 MockRead("HTTP/1.1 302 Redirect\r\n"),
1020 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591021 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551022 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061023 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551024 };
1025
1026 HttpRequestInfo request;
1027 request.method = "GET";
1028 request.url = GURL("http://redirect.com/");
1029 request.load_flags = 0;
1030
mmenkee65e7af2015-10-13 17:16:421031 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1628fe92011-10-04 23:04:551032 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411033 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]1628fe92011-10-04 23:04:551034
1035 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071036 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551037
[email protected]49639fa2011-12-20 23:22:411038 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551039
[email protected]49639fa2011-12-20 23:22:411040 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1628fe92011-10-04 23:04:551041 EXPECT_EQ(ERR_IO_PENDING, rv);
1042
1043 EXPECT_EQ(OK, callback.WaitForResult());
1044
1045 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501046 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
[email protected]1628fe92011-10-04 23:04:551047 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1048 std::string url;
1049 EXPECT_TRUE(response->headers->IsRedirect(&url));
1050 EXPECT_EQ("http://good.com/", url);
[email protected]d8fc4722014-06-13 13:17:151051 EXPECT_TRUE(response->proxy_server.IsEmpty());
[email protected]1628fe92011-10-04 23:04:551052}
1053
[email protected]1628fe92011-10-04 23:04:551054// Checks that two distinct Location headers result in an error.
[email protected]23e482282013-06-14 16:08:021055TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551056 MockRead data_reads[] = {
1057 MockRead("HTTP/1.1 302 Redirect\r\n"),
1058 MockRead("Location: http://good.com/\r\n"),
1059 MockRead("Location: http://evil.com/\r\n"),
1060 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061061 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551062 };
1063 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1064 arraysize(data_reads));
1065 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
1066}
1067
[email protected]ef0faf2e72009-03-05 23:27:231068// Do a request using the HEAD method. Verify that we don't try to read the
1069// message body (since HEAD has none).
[email protected]23e482282013-06-14 16:08:021070TEST_P(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421071 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231072 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231073 request.url = GURL("http://www.example.org/");
[email protected]ef0faf2e72009-03-05 23:27:231074 request.load_flags = 0;
1075
mmenkee65e7af2015-10-13 17:16:421076 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271077 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411078 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]597a1ab2014-06-26 08:12:271079 BeforeProxyHeadersSentHandler proxy_headers_handler;
1080 trans->SetBeforeProxyHeadersSentCallback(
1081 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
1082 base::Unretained(&proxy_headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271083
[email protected]ef0faf2e72009-03-05 23:27:231084 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131085 MockWrite("HEAD / HTTP/1.1\r\n"
1086 "Host: www.example.org\r\n"
1087 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231088 };
1089 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231090 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1091 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231092
mmenked39192ee2015-12-09 00:57:231093 // No response body because the test stops reading here.
1094 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231095 };
1096
[email protected]31a2bfe2010-02-09 08:03:391097 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1098 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:071099 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231100
[email protected]49639fa2011-12-20 23:22:411101 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231102
[email protected]49639fa2011-12-20 23:22:411103 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421104 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:231105
1106 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421107 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:231108
[email protected]1c773ea12009-04-28 19:58:421109 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501110 ASSERT_TRUE(response != NULL);
[email protected]ef0faf2e72009-03-05 23:27:231111
1112 // Check that the headers got parsed.
[email protected]90499482013-06-01 00:39:501113 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]ef0faf2e72009-03-05 23:27:231114 EXPECT_EQ(1234, response->headers->GetContentLength());
1115 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151116 EXPECT_TRUE(response->proxy_server.IsEmpty());
[email protected]597a1ab2014-06-26 08:12:271117 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
[email protected]ef0faf2e72009-03-05 23:27:231118
1119 std::string server_header;
1120 void* iter = NULL;
1121 bool has_server_header = response->headers->EnumerateHeader(
1122 &iter, "Server", &server_header);
1123 EXPECT_TRUE(has_server_header);
1124 EXPECT_EQ("Blah", server_header);
1125
1126 // Reading should give EOF right away, since there is no message body
1127 // (despite non-zero content-length).
1128 std::string response_data;
1129 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421130 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:231131 EXPECT_EQ("", response_data);
1132}
1133
[email protected]23e482282013-06-14 16:08:021134TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
mmenkee65e7af2015-10-13 17:16:421135 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521136
1137 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351138 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1139 MockRead("hello"),
1140 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1141 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061142 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521143 };
[email protected]31a2bfe2010-02-09 08:03:391144 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071145 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521146
[email protected]0b0bf032010-09-21 18:08:501147 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521148 "hello", "world"
1149 };
1150
1151 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421152 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521153 request.method = "GET";
bncce36dca22015-04-21 22:11:231154 request.url = GURL("http://www.example.org/");
initial.commit586acc5fe2008-07-26 22:42:521155 request.load_flags = 0;
1156
[email protected]262eec82013-03-19 21:01:361157 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501158 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271159
[email protected]49639fa2011-12-20 23:22:411160 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521161
[email protected]49639fa2011-12-20 23:22:411162 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421163 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521164
1165 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421166 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521167
[email protected]1c773ea12009-04-28 19:58:421168 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501169 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521170
[email protected]90499482013-06-01 00:39:501171 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251172 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151173 EXPECT_TRUE(response->proxy_server.IsEmpty());
initial.commit586acc5fe2008-07-26 22:42:521174
1175 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571176 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421177 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251178 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521179 }
1180}
1181
[email protected]23e482282013-06-14 16:08:021182TEST_P(HttpNetworkTransactionTest, Ignores100) {
olli.raula6df48b2a2015-11-26 07:40:221183 std::vector<scoped_ptr<UploadElementReader>> element_readers;
1184 element_readers.push_back(
1185 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
1186 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271187
[email protected]1c773ea12009-04-28 19:58:421188 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521189 request.method = "POST";
1190 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271191 request.upload_data_stream = &upload_data_stream;
initial.commit586acc5fe2008-07-26 22:42:521192 request.load_flags = 0;
1193
mmenkee65e7af2015-10-13 17:16:421194 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271195 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411196 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271197
initial.commit586acc5fe2008-07-26 22:42:521198 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351199 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1200 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1201 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061202 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521203 };
[email protected]31a2bfe2010-02-09 08:03:391204 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071205 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521206
[email protected]49639fa2011-12-20 23:22:411207 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521208
[email protected]49639fa2011-12-20 23:22:411209 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421210 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521211
1212 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421213 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521214
[email protected]1c773ea12009-04-28 19:58:421215 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501216 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521217
[email protected]90499482013-06-01 00:39:501218 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251219 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521220
1221 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571222 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421223 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251224 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521225}
1226
[email protected]3a2d3662009-03-27 03:49:141227// This test is almost the same as Ignores100 above, but the response contains
1228// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571229// HTTP/1.1 and the two status headers are read in one read.
[email protected]23e482282013-06-14 16:08:021230TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421231 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141232 request.method = "GET";
1233 request.url = GURL("http://www.foo.com/");
1234 request.load_flags = 0;
1235
mmenkee65e7af2015-10-13 17:16:421236 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271237 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411238 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271239
[email protected]3a2d3662009-03-27 03:49:141240 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571241 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1242 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141243 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061244 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141245 };
[email protected]31a2bfe2010-02-09 08:03:391246 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071247 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141248
[email protected]49639fa2011-12-20 23:22:411249 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141250
[email protected]49639fa2011-12-20 23:22:411251 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421252 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:141253
1254 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421255 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:141256
[email protected]1c773ea12009-04-28 19:58:421257 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501258 ASSERT_TRUE(response != NULL);
[email protected]3a2d3662009-03-27 03:49:141259
[email protected]90499482013-06-01 00:39:501260 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3a2d3662009-03-27 03:49:141261 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1262
1263 std::string response_data;
1264 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421265 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:141266 EXPECT_EQ("hello world", response_data);
1267}
1268
[email protected]23e482282013-06-14 16:08:021269TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081270 HttpRequestInfo request;
1271 request.method = "POST";
1272 request.url = GURL("http://www.foo.com/");
1273 request.load_flags = 0;
1274
mmenkee65e7af2015-10-13 17:16:421275 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
zmo9528c9f42015-08-04 22:12:081276 scoped_ptr<HttpTransaction> trans(
1277 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1278
1279 MockRead data_reads[] = {
1280 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1281 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381282 };
zmo9528c9f42015-08-04 22:12:081283 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1284 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381285
zmo9528c9f42015-08-04 22:12:081286 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381287
zmo9528c9f42015-08-04 22:12:081288 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1289 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ee9410e72010-01-07 01:42:381290
zmo9528c9f42015-08-04 22:12:081291 rv = callback.WaitForResult();
1292 EXPECT_EQ(OK, rv);
[email protected]ee9410e72010-01-07 01:42:381293
zmo9528c9f42015-08-04 22:12:081294 std::string response_data;
1295 rv = ReadTransaction(trans.get(), &response_data);
1296 EXPECT_EQ(OK, rv);
1297 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381298}
1299
[email protected]23e482282013-06-14 16:08:021300TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381301 HttpRequestInfo request;
1302 request.method = "POST";
1303 request.url = GURL("http://www.foo.com/");
1304 request.load_flags = 0;
1305
mmenkee65e7af2015-10-13 17:16:421306 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271307 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411308 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271309
[email protected]ee9410e72010-01-07 01:42:381310 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061311 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381312 };
[email protected]31a2bfe2010-02-09 08:03:391313 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071314 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381315
[email protected]49639fa2011-12-20 23:22:411316 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381317
[email protected]49639fa2011-12-20 23:22:411318 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:381319 EXPECT_EQ(ERR_IO_PENDING, rv);
1320
1321 rv = callback.WaitForResult();
1322 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1323}
1324
[email protected]23e482282013-06-14 16:08:021325void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511326 const MockWrite* write_failure,
1327 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421328 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521329 request.method = "GET";
1330 request.url = GURL("http://www.foo.com/");
1331 request.load_flags = 0;
1332
vishal.b62985ca92015-04-17 08:45:511333 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071334 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421335 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271336
[email protected]202965992011-12-07 23:04:511337 // Written data for successfully sending both requests.
1338 MockWrite data1_writes[] = {
1339 MockWrite("GET / HTTP/1.1\r\n"
1340 "Host: www.foo.com\r\n"
1341 "Connection: keep-alive\r\n\r\n"),
1342 MockWrite("GET / HTTP/1.1\r\n"
1343 "Host: www.foo.com\r\n"
1344 "Connection: keep-alive\r\n\r\n")
1345 };
1346
1347 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521348 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351349 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1350 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061351 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521352 };
[email protected]202965992011-12-07 23:04:511353
1354 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491355 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511356 data1_writes[1] = *write_failure;
1357 } else {
1358 ASSERT_TRUE(read_failure);
1359 data1_reads[2] = *read_failure;
1360 }
1361
1362 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1363 data1_writes, arraysize(data1_writes));
[email protected]bb88e1d32013-05-03 23:11:071364 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521365
1366 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351367 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1368 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061369 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521370 };
[email protected]31a2bfe2010-02-09 08:03:391371 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071372 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521373
thestig9d3bb0c2015-01-24 00:49:511374 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521375 "hello", "world"
1376 };
1377
[email protected]58e32bb2013-01-21 18:23:251378 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521379 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411380 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521381
[email protected]262eec82013-03-19 21:01:361382 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501383 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
initial.commit586acc5fe2008-07-26 22:42:521384
[email protected]49639fa2011-12-20 23:22:411385 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421386 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521387
1388 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421389 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521390
[email protected]58e32bb2013-01-21 18:23:251391 LoadTimingInfo load_timing_info;
1392 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1393 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1394 if (i == 0) {
1395 first_socket_log_id = load_timing_info.socket_log_id;
1396 } else {
1397 // The second request should be using a new socket.
1398 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1399 }
1400
[email protected]1c773ea12009-04-28 19:58:421401 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501402 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521403
[email protected]90499482013-06-01 00:39:501404 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251405 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521406
1407 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571408 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421409 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251410 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521411 }
1412}
[email protected]3d2a59b2008-09-26 19:44:251413
[email protected]a34f61ee2014-03-18 20:59:491414void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1415 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101416 const MockRead* read_failure,
1417 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491418 HttpRequestInfo request;
1419 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101420 request.url = GURL("https://www.foo.com/");
[email protected]a34f61ee2014-03-18 20:59:491421 request.load_flags = 0;
1422
vishal.b62985ca92015-04-17 08:45:511423 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491424 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421425 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491426
[email protected]09356c652014-03-25 15:36:101427 SSLSocketDataProvider ssl1(ASYNC, OK);
1428 SSLSocketDataProvider ssl2(ASYNC, OK);
1429 if (use_spdy) {
rdsmithebb50aa2015-11-12 03:44:381430 ssl1.SetNextProto(GetProtocol());
1431 ssl2.SetNextProto(GetProtocol());
[email protected]09356c652014-03-25 15:36:101432 }
1433 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1434 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491435
[email protected]09356c652014-03-25 15:36:101436 // SPDY versions of the request and response.
1437 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1438 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1439 scoped_ptr<SpdyFrame> spdy_response(
1440 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1441 scoped_ptr<SpdyFrame> spdy_data(
1442 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
[email protected]a34f61ee2014-03-18 20:59:491443
[email protected]09356c652014-03-25 15:36:101444 // HTTP/1.1 versions of the request and response.
1445 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1446 "Host: www.foo.com\r\n"
1447 "Connection: keep-alive\r\n\r\n";
1448 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1449 const char kHttpData[] = "hello";
1450
1451 std::vector<MockRead> data1_reads;
1452 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491453 if (write_failure) {
1454 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101455 data1_writes.push_back(*write_failure);
1456 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491457 } else {
1458 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101459 if (use_spdy) {
1460 data1_writes.push_back(CreateMockWrite(*spdy_request));
1461 } else {
1462 data1_writes.push_back(MockWrite(kHttpRequest));
1463 }
1464 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491465 }
1466
[email protected]09356c652014-03-25 15:36:101467 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1468 &data1_writes[0], data1_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491469 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1470
[email protected]09356c652014-03-25 15:36:101471 std::vector<MockRead> data2_reads;
1472 std::vector<MockWrite> data2_writes;
1473
1474 if (use_spdy) {
1475 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1476
1477 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1478 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1479 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1480 } else {
1481 data2_writes.push_back(
1482 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1483
1484 data2_reads.push_back(
1485 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1486 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1487 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1488 }
rch8e6c6c42015-05-01 14:05:131489 SequencedSocketData data2(&data2_reads[0], data2_reads.size(),
1490 &data2_writes[0], data2_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491491 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1492
1493 // Preconnect a socket.
ttuttle859dc7a2015-04-23 19:42:291494 SSLConfig ssl_config;
[email protected]a34f61ee2014-03-18 20:59:491495 session->ssl_config_service()->GetSSLConfig(&ssl_config);
bnc1f295372015-10-21 23:24:221496 session->GetAlpnProtos(&ssl_config.alpn_protos);
1497 session->GetNpnProtos(&ssl_config.npn_protos);
mmenked1205bd2015-07-15 22:26:351498 session->http_stream_factory()->PreconnectStreams(1, request, ssl_config,
1499 ssl_config);
[email protected]a34f61ee2014-03-18 20:59:491500 // Wait for the preconnect to complete.
1501 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1502 base::RunLoop().RunUntilIdle();
[email protected]09356c652014-03-25 15:36:101503 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491504
1505 // Make the request.
1506 TestCompletionCallback callback;
1507
1508 scoped_ptr<HttpTransaction> trans(
1509 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1510
1511 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1512 EXPECT_EQ(ERR_IO_PENDING, rv);
1513
1514 rv = callback.WaitForResult();
1515 EXPECT_EQ(OK, rv);
1516
1517 LoadTimingInfo load_timing_info;
1518 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101519 TestLoadTimingNotReused(
1520 load_timing_info,
1521 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491522
1523 const HttpResponseInfo* response = trans->GetResponseInfo();
1524 ASSERT_TRUE(response != NULL);
1525
1526 EXPECT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:021527 if (response->was_fetched_via_spdy) {
1528 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1529 } else {
1530 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1531 }
[email protected]a34f61ee2014-03-18 20:59:491532
1533 std::string response_data;
1534 rv = ReadTransaction(trans.get(), &response_data);
1535 EXPECT_EQ(OK, rv);
[email protected]09356c652014-03-25 15:36:101536 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491537}
1538
[email protected]23e482282013-06-14 16:08:021539TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:231540 KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061541 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]202965992011-12-07 23:04:511542 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1543}
1544
[email protected]23e482282013-06-14 16:08:021545TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061546 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]202965992011-12-07 23:04:511547 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251548}
1549
[email protected]23e482282013-06-14 16:08:021550TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061551 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]202965992011-12-07 23:04:511552 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251553}
1554
[email protected]d58ceea82014-06-04 10:55:541555// Make sure that on a 408 response (Request Timeout), the request is retried,
1556// if the socket was a reused keep alive socket.
1557TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1558 MockRead read_failure(SYNCHRONOUS,
1559 "HTTP/1.1 408 Request Timeout\r\n"
1560 "Connection: Keep-Alive\r\n"
1561 "Content-Length: 6\r\n\r\n"
1562 "Pickle");
1563 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1564}
1565
[email protected]a34f61ee2014-03-18 20:59:491566TEST_P(HttpNetworkTransactionTest,
1567 PreconnectErrorNotConnectedOnWrite) {
1568 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]09356c652014-03-25 15:36:101569 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
[email protected]a34f61ee2014-03-18 20:59:491570}
1571
1572TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1573 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]09356c652014-03-25 15:36:101574 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491575}
1576
1577TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1578 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]09356c652014-03-25 15:36:101579 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1580}
1581
1582TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1583 MockRead read_failure(ASYNC, OK); // EOF
1584 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1585}
1586
[email protected]d58ceea82014-06-04 10:55:541587// Make sure that on a 408 response (Request Timeout), the request is retried,
1588// if the socket was a preconnected (UNUSED_IDLE) socket.
1589TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1590 MockRead read_failure(SYNCHRONOUS,
1591 "HTTP/1.1 408 Request Timeout\r\n"
1592 "Connection: Keep-Alive\r\n"
1593 "Content-Length: 6\r\n\r\n"
1594 "Pickle");
1595 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1596 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1597}
1598
[email protected]09356c652014-03-25 15:36:101599TEST_P(HttpNetworkTransactionTest,
1600 SpdyPreconnectErrorNotConnectedOnWrite) {
1601 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1602 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1603}
1604
1605TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1606 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1607 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1608}
1609
1610TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1611 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1612 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1613}
1614
1615TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1616 MockRead read_failure(ASYNC, OK); // EOF
1617 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:491618}
1619
[email protected]23e482282013-06-14 16:08:021620TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421621 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251622 request.method = "GET";
bncce36dca22015-04-21 22:11:231623 request.url = GURL("http://www.example.org/");
[email protected]3d2a59b2008-09-26 19:44:251624 request.load_flags = 0;
1625
mmenkee65e7af2015-10-13 17:16:421626 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271627 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411628 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271629
[email protected]3d2a59b2008-09-26 19:44:251630 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061631 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:351632 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1633 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061634 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251635 };
[email protected]31a2bfe2010-02-09 08:03:391636 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071637 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:251638
[email protected]49639fa2011-12-20 23:22:411639 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:251640
[email protected]49639fa2011-12-20 23:22:411641 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421642 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:251643
1644 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421645 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
ttuttled9dbc652015-09-29 20:00:591646
1647 IPEndPoint endpoint;
1648 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
1649 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:251650}
1651
1652// What do various browsers do when the server closes a non-keepalive
1653// connection without sending any response header or body?
1654//
1655// IE7: error page
1656// Safari 3.1.2 (Windows): error page
1657// Firefox 3.0.1: blank page
1658// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:421659// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1660// Us: error page (EMPTY_RESPONSE)
[email protected]23e482282013-06-14 16:08:021661TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:251662 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061663 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:351664 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1665 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061666 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251667 };
[email protected]31a2bfe2010-02-09 08:03:391668 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1669 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:421670 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:251671}
[email protected]038e9a32008-10-08 22:40:161672
[email protected]1826a402014-01-08 15:40:481673// Test that network access can be deferred and resumed.
1674TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1675 HttpRequestInfo request;
1676 request.method = "GET";
bncce36dca22015-04-21 22:11:231677 request.url = GURL("http://www.example.org/");
[email protected]1826a402014-01-08 15:40:481678 request.load_flags = 0;
1679
mmenkee65e7af2015-10-13 17:16:421680 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1826a402014-01-08 15:40:481681 scoped_ptr<HttpTransaction> trans(
1682 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1683
1684 // Defer on OnBeforeNetworkStart.
1685 BeforeNetworkStartHandler net_start_handler(true); // defer
1686 trans->SetBeforeNetworkStartCallback(
1687 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1688 base::Unretained(&net_start_handler)));
1689
1690 MockRead data_reads[] = {
1691 MockRead("HTTP/1.0 200 OK\r\n"),
1692 MockRead("Content-Length: 5\r\n\r\n"),
1693 MockRead("hello"),
1694 MockRead(SYNCHRONOUS, 0),
1695 };
1696 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1697 session_deps_.socket_factory->AddSocketDataProvider(&data);
1698
1699 TestCompletionCallback callback;
1700
1701 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1702 EXPECT_EQ(ERR_IO_PENDING, rv);
1703 base::MessageLoop::current()->RunUntilIdle();
1704
1705 // Should have deferred for network start.
1706 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1707 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
[email protected]1826a402014-01-08 15:40:481708
1709 trans->ResumeNetworkStart();
1710 rv = callback.WaitForResult();
1711 EXPECT_EQ(OK, rv);
1712 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1713
1714 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1715 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1716 if (rv == ERR_IO_PENDING)
1717 rv = callback.WaitForResult();
1718 EXPECT_EQ(5, rv);
1719 trans.reset();
1720}
1721
1722// Test that network use can be deferred and canceled.
1723TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1724 HttpRequestInfo request;
1725 request.method = "GET";
bncce36dca22015-04-21 22:11:231726 request.url = GURL("http://www.example.org/");
[email protected]1826a402014-01-08 15:40:481727 request.load_flags = 0;
1728
mmenkee65e7af2015-10-13 17:16:421729 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1826a402014-01-08 15:40:481730 scoped_ptr<HttpTransaction> trans(
1731 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1732
1733 // Defer on OnBeforeNetworkStart.
1734 BeforeNetworkStartHandler net_start_handler(true); // defer
1735 trans->SetBeforeNetworkStartCallback(
1736 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1737 base::Unretained(&net_start_handler)));
1738
1739 TestCompletionCallback callback;
1740
1741 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1742 EXPECT_EQ(ERR_IO_PENDING, rv);
1743 base::MessageLoop::current()->RunUntilIdle();
1744
1745 // Should have deferred for network start.
1746 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1747 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
[email protected]1826a402014-01-08 15:40:481748}
1749
[email protected]7a5378b2012-11-04 03:25:171750// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1751// tests. There was a bug causing HttpNetworkTransaction to hang in the
1752// destructor in such situations.
1753// See http://crbug.com/154712 and http://crbug.com/156609.
[email protected]23e482282013-06-14 16:08:021754TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:171755 HttpRequestInfo request;
1756 request.method = "GET";
bncce36dca22015-04-21 22:11:231757 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171758 request.load_flags = 0;
1759
mmenkee65e7af2015-10-13 17:16:421760 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:361761 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501762 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171763
1764 MockRead data_reads[] = {
1765 MockRead("HTTP/1.0 200 OK\r\n"),
1766 MockRead("Connection: keep-alive\r\n"),
1767 MockRead("Content-Length: 100\r\n\r\n"),
1768 MockRead("hello"),
1769 MockRead(SYNCHRONOUS, 0),
1770 };
1771 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071772 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171773
1774 TestCompletionCallback callback;
1775
1776 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1777 EXPECT_EQ(ERR_IO_PENDING, rv);
1778
1779 rv = callback.WaitForResult();
1780 EXPECT_EQ(OK, rv);
1781
1782 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501783 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171784 if (rv == ERR_IO_PENDING)
1785 rv = callback.WaitForResult();
1786 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:501787 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171788 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1789
1790 trans.reset();
[email protected]2da659e2013-05-23 20:51:341791 base::MessageLoop::current()->RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171792 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1793}
1794
[email protected]23e482282013-06-14 16:08:021795TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:171796 HttpRequestInfo request;
1797 request.method = "GET";
bncce36dca22015-04-21 22:11:231798 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171799 request.load_flags = 0;
1800
mmenkee65e7af2015-10-13 17:16:421801 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:361802 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501803 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171804
1805 MockRead data_reads[] = {
1806 MockRead("HTTP/1.0 200 OK\r\n"),
1807 MockRead("Connection: keep-alive\r\n"),
1808 MockRead("Content-Length: 100\r\n\r\n"),
1809 MockRead(SYNCHRONOUS, 0),
1810 };
1811 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071812 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171813
1814 TestCompletionCallback callback;
1815
1816 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1817 EXPECT_EQ(ERR_IO_PENDING, rv);
1818
1819 rv = callback.WaitForResult();
1820 EXPECT_EQ(OK, rv);
1821
1822 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501823 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171824 if (rv == ERR_IO_PENDING)
1825 rv = callback.WaitForResult();
1826 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1827
1828 trans.reset();
[email protected]2da659e2013-05-23 20:51:341829 base::MessageLoop::current()->RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171830 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1831}
1832
[email protected]0b0bf032010-09-21 18:08:501833// Test that we correctly reuse a keep-alive connection after not explicitly
1834// reading the body.
[email protected]23e482282013-06-14 16:08:021835TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:131836 HttpRequestInfo request;
1837 request.method = "GET";
1838 request.url = GURL("http://www.foo.com/");
1839 request.load_flags = 0;
1840
vishal.b62985ca92015-04-17 08:45:511841 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071842 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421843 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271844
mmenkecc2298e2015-12-07 18:20:181845 const char* request_data =
1846 "GET / HTTP/1.1\r\n"
1847 "Host: www.foo.com\r\n"
1848 "Connection: keep-alive\r\n\r\n";
1849 MockWrite data_writes[] = {
1850 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
1851 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
1852 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
1853 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
1854 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
1855 };
1856
[email protected]0b0bf032010-09-21 18:08:501857 // Note that because all these reads happen in the same
1858 // StaticSocketDataProvider, it shows that the same socket is being reused for
1859 // all transactions.
mmenkecc2298e2015-12-07 18:20:181860 MockRead data_reads[] = {
1861 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
1862 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
1863 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
1864 MockRead(ASYNC, 7,
1865 "HTTP/1.1 302 Found\r\n"
1866 "Content-Length: 0\r\n\r\n"),
1867 MockRead(ASYNC, 9,
1868 "HTTP/1.1 302 Found\r\n"
1869 "Content-Length: 5\r\n\r\n"
1870 "hello"),
1871 MockRead(ASYNC, 11,
1872 "HTTP/1.1 301 Moved Permanently\r\n"
1873 "Content-Length: 0\r\n\r\n"),
1874 MockRead(ASYNC, 13,
1875 "HTTP/1.1 301 Moved Permanently\r\n"
1876 "Content-Length: 5\r\n\r\n"
1877 "hello"),
[email protected]fc31d6a42010-06-24 18:05:131878
mmenkecc2298e2015-12-07 18:20:181879 // In the next two rounds, IsConnectedAndIdle returns false, due to
1880 // the set_busy_before_sync_reads(true) call, while the
1881 // HttpNetworkTransaction is being shut down, but the socket is still
1882 // reuseable. See http://crbug.com/544255.
1883 MockRead(ASYNC, 15,
1884 "HTTP/1.1 200 Hunky-Dory\r\n"
1885 "Content-Length: 5\r\n\r\n"),
1886 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:131887
mmenkecc2298e2015-12-07 18:20:181888 MockRead(ASYNC, 18,
1889 "HTTP/1.1 200 Hunky-Dory\r\n"
1890 "Content-Length: 5\r\n\r\n"
1891 "he"),
1892 MockRead(SYNCHRONOUS, 19, "llo"),
1893
1894 // The body of the final request is actually read.
1895 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1896 MockRead(ASYNC, 22, "hello"),
1897 };
1898 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
1899 arraysize(data_writes));
1900 data.set_busy_before_sync_reads(true);
1901 session_deps_.socket_factory->AddSocketDataProvider(&data);
1902
1903 const int kNumUnreadBodies = arraysize(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:501904 std::string response_lines[kNumUnreadBodies];
1905
[email protected]58e32bb2013-01-21 18:23:251906 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
mmenkecc2298e2015-12-07 18:20:181907 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:411908 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:131909
[email protected]262eec82013-03-19 21:01:361910 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501911 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]fc31d6a42010-06-24 18:05:131912
[email protected]49639fa2011-12-20 23:22:411913 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
mmenkecc2298e2015-12-07 18:20:181914 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]fc31d6a42010-06-24 18:05:131915
[email protected]58e32bb2013-01-21 18:23:251916 LoadTimingInfo load_timing_info;
1917 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1918 if (i == 0) {
1919 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1920 first_socket_log_id = load_timing_info.socket_log_id;
1921 } else {
1922 TestLoadTimingReused(load_timing_info);
1923 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1924 }
1925
[email protected]fc31d6a42010-06-24 18:05:131926 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:181927 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:131928
mmenkecc2298e2015-12-07 18:20:181929 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:501930 response_lines[i] = response->headers->GetStatusLine();
1931
mmenkecc2298e2015-12-07 18:20:181932 // Delete the transaction without reading the response bodies. Then spin
1933 // the message loop, so the response bodies are drained.
1934 trans.reset();
1935 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:131936 }
[email protected]0b0bf032010-09-21 18:08:501937
1938 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:181939 "HTTP/1.1 204 No Content",
1940 "HTTP/1.1 205 Reset Content",
1941 "HTTP/1.1 304 Not Modified",
1942 "HTTP/1.1 302 Found",
1943 "HTTP/1.1 302 Found",
1944 "HTTP/1.1 301 Moved Permanently",
1945 "HTTP/1.1 301 Moved Permanently",
1946 "HTTP/1.1 200 Hunky-Dory",
1947 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:501948 };
1949
mostynb91e0da982015-01-20 19:17:271950 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1951 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:501952
1953 for (int i = 0; i < kNumUnreadBodies; ++i)
1954 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1955
[email protected]49639fa2011-12-20 23:22:411956 TestCompletionCallback callback;
[email protected]262eec82013-03-19 21:01:361957 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501958 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:411959 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
mmenkecc2298e2015-12-07 18:20:181960 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]0b0bf032010-09-21 18:08:501961 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:181962 ASSERT_TRUE(response);
1963 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:501964 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1965 std::string response_data;
1966 rv = ReadTransaction(trans.get(), &response_data);
1967 EXPECT_EQ(OK, rv);
1968 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131969}
1970
[email protected]038e9a32008-10-08 22:40:161971// Test the request-challenge-retry sequence for basic auth.
1972// (basic auth is the easiest to mock, because it has no randomness).
[email protected]23e482282013-06-14 16:08:021973TEST_P(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421974 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161975 request.method = "GET";
bncce36dca22015-04-21 22:11:231976 request.url = GURL("http://www.example.org/");
[email protected]038e9a32008-10-08 22:40:161977 request.load_flags = 0;
1978
vishal.b62985ca92015-04-17 08:45:511979 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:071980 session_deps_.net_log = &log;
mmenkee65e7af2015-10-13 17:16:421981 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271982 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411983 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271984
[email protected]f9ee6b52008-11-08 06:46:231985 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:231986 MockWrite(
1987 "GET / HTTP/1.1\r\n"
1988 "Host: www.example.org\r\n"
1989 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:231990 };
1991
[email protected]038e9a32008-10-08 22:40:161992 MockRead data_reads1[] = {
1993 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1994 // Give a couple authenticate options (only the middle one is actually
1995 // supported).
[email protected]22927ad2009-09-21 19:56:191996 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161997 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1998 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1999 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2000 // Large content-length -- won't matter, as connection will be reset.
2001 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062002 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162003 };
2004
2005 // After calling trans->RestartWithAuth(), this is the request we should
2006 // be issuing -- the final header line contains the credentials.
2007 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232008 MockWrite(
2009 "GET / HTTP/1.1\r\n"
2010 "Host: www.example.org\r\n"
2011 "Connection: keep-alive\r\n"
2012 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162013 };
2014
2015 // Lastly, the server responds with the actual content.
2016 MockRead data_reads2[] = {
2017 MockRead("HTTP/1.0 200 OK\r\n"),
2018 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2019 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062020 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162021 };
2022
[email protected]31a2bfe2010-02-09 08:03:392023 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2024 data_writes1, arraysize(data_writes1));
2025 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2026 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:072027 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2028 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162029
[email protected]49639fa2011-12-20 23:22:412030 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162031
[email protected]49639fa2011-12-20 23:22:412032 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422033 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162034
2035 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422036 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162037
[email protected]58e32bb2013-01-21 18:23:252038 LoadTimingInfo load_timing_info1;
2039 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2040 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2041
sclittlefb249892015-09-10 21:33:222042 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2043 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2044 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
[email protected]b8015c42013-12-24 15:18:192045 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2046
[email protected]1c773ea12009-04-28 19:58:422047 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502048 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042049 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162050
[email protected]49639fa2011-12-20 23:22:412051 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162052
[email protected]49639fa2011-12-20 23:22:412053 rv = trans->RestartWithAuth(
2054 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422055 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162056
2057 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422058 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162059
[email protected]58e32bb2013-01-21 18:23:252060 LoadTimingInfo load_timing_info2;
2061 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2062 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2063 // The load timing after restart should have a new socket ID, and times after
2064 // those of the first load timing.
2065 EXPECT_LE(load_timing_info1.receive_headers_end,
2066 load_timing_info2.connect_timing.connect_start);
2067 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2068
sclittlefb249892015-09-10 21:33:222069 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2070 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2071 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
[email protected]b8015c42013-12-24 15:18:192072 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2073
[email protected]038e9a32008-10-08 22:40:162074 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502075 ASSERT_TRUE(response != NULL);
[email protected]038e9a32008-10-08 22:40:162076 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2077 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162078}
2079
ttuttled9dbc652015-09-29 20:00:592080// Test the request-challenge-retry sequence for basic auth.
2081// (basic auth is the easiest to mock, because it has no randomness).
2082TEST_P(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
2083 HttpRequestInfo request;
2084 request.method = "GET";
2085 request.url = GURL("http://www.example.org/");
2086 request.load_flags = 0;
2087
2088 TestNetLog log;
2089 MockHostResolver* resolver = new MockHostResolver();
2090 session_deps_.net_log = &log;
2091 session_deps_.host_resolver.reset(resolver);
mmenkee65e7af2015-10-13 17:16:422092 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
ttuttled9dbc652015-09-29 20:00:592093 scoped_ptr<HttpTransaction> trans(
2094 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2095
2096 resolver->rules()->ClearRules();
2097 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2098
2099 MockWrite data_writes1[] = {
2100 MockWrite("GET / HTTP/1.1\r\n"
2101 "Host: www.example.org\r\n"
2102 "Connection: keep-alive\r\n\r\n"),
2103 };
2104
2105 MockRead data_reads1[] = {
2106 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2107 // Give a couple authenticate options (only the middle one is actually
2108 // supported).
2109 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2110 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2111 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2112 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2113 // Large content-length -- won't matter, as connection will be reset.
2114 MockRead("Content-Length: 10000\r\n\r\n"),
2115 MockRead(SYNCHRONOUS, ERR_FAILED),
2116 };
2117
2118 // After calling trans->RestartWithAuth(), this is the request we should
2119 // be issuing -- the final header line contains the credentials.
2120 MockWrite data_writes2[] = {
2121 MockWrite("GET / HTTP/1.1\r\n"
2122 "Host: www.example.org\r\n"
2123 "Connection: keep-alive\r\n"
2124 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2125 };
2126
2127 // Lastly, the server responds with the actual content.
2128 MockRead data_reads2[] = {
2129 MockRead("HTTP/1.0 200 OK\r\n"),
2130 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2131 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2132 };
2133
2134 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2135 data_writes1, arraysize(data_writes1));
2136 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2137 data_writes2, arraysize(data_writes2));
2138 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2139 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2140
2141 TestCompletionCallback callback1;
2142
2143 EXPECT_EQ(OK, callback1.GetResult(trans->Start(&request, callback1.callback(),
2144 BoundNetLog())));
2145
2146 LoadTimingInfo load_timing_info1;
2147 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2148 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2149
2150 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2151 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2152 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
2153 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2154
2155 const HttpResponseInfo* response = trans->GetResponseInfo();
2156 ASSERT_TRUE(response);
2157 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2158
2159 IPEndPoint endpoint;
2160 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2161 ASSERT_FALSE(endpoint.address().empty());
2162 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2163
2164 resolver->rules()->ClearRules();
2165 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2166
2167 TestCompletionCallback callback2;
2168
2169 EXPECT_EQ(OK, callback2.GetResult(trans->RestartWithAuth(
2170 AuthCredentials(kFoo, kBar), callback2.callback())));
2171
2172 LoadTimingInfo load_timing_info2;
2173 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2174 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2175 // The load timing after restart should have a new socket ID, and times after
2176 // those of the first load timing.
2177 EXPECT_LE(load_timing_info1.receive_headers_end,
2178 load_timing_info2.connect_timing.connect_start);
2179 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2180
2181 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2182 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2183 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
2184 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2185
2186 response = trans->GetResponseInfo();
2187 ASSERT_TRUE(response);
2188 EXPECT_FALSE(response->auth_challenge.get());
2189 EXPECT_EQ(100, response->headers->GetContentLength());
2190
2191 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2192 ASSERT_FALSE(endpoint.address().empty());
2193 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2194}
2195
[email protected]23e482282013-06-14 16:08:022196TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462197 HttpRequestInfo request;
2198 request.method = "GET";
bncce36dca22015-04-21 22:11:232199 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292200 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]861fcd52009-08-26 02:33:462201
mmenkee65e7af2015-10-13 17:16:422202 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272203 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:412204 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:272205
[email protected]861fcd52009-08-26 02:33:462206 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232207 MockWrite(
2208 "GET / HTTP/1.1\r\n"
2209 "Host: www.example.org\r\n"
2210 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462211 };
2212
2213 MockRead data_reads[] = {
2214 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2215 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2216 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2217 // Large content-length -- won't matter, as connection will be reset.
2218 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062219 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462220 };
2221
[email protected]31a2bfe2010-02-09 08:03:392222 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2223 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:072224 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412225 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462226
[email protected]49639fa2011-12-20 23:22:412227 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]861fcd52009-08-26 02:33:462228 EXPECT_EQ(ERR_IO_PENDING, rv);
2229
2230 rv = callback.WaitForResult();
2231 EXPECT_EQ(0, rv);
2232
sclittlefb249892015-09-10 21:33:222233 int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes));
2234 EXPECT_EQ(writes_size, trans->GetTotalSentBytes());
2235 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
[email protected]b8015c42013-12-24 15:18:192236 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2237
[email protected]861fcd52009-08-26 02:33:462238 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502239 ASSERT_TRUE(response != NULL);
[email protected]861fcd52009-08-26 02:33:462240 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2241}
2242
[email protected]2d2697f92009-02-18 21:00:322243// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2244// connection.
[email protected]23e482282013-06-14 16:08:022245TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182246 // On the second pass, the body read of the auth challenge is synchronous, so
2247 // IsConnectedAndIdle returns false. The socket should still be drained and
2248 // reused. See http://crbug.com/544255.
2249 for (int i = 0; i < 2; ++i) {
2250 HttpRequestInfo request;
2251 request.method = "GET";
2252 request.url = GURL("http://www.example.org/");
2253 request.load_flags = 0;
[email protected]2d2697f92009-02-18 21:00:322254
mmenkecc2298e2015-12-07 18:20:182255 TestNetLog log;
2256 session_deps_.net_log = &log;
2257 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272258
mmenkecc2298e2015-12-07 18:20:182259 MockWrite data_writes[] = {
2260 MockWrite(ASYNC, 0,
2261 "GET / HTTP/1.1\r\n"
2262 "Host: www.example.org\r\n"
2263 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322264
mmenkecc2298e2015-12-07 18:20:182265 // After calling trans->RestartWithAuth(), this is the request we should
2266 // be issuing -- the final header line contains the credentials.
2267 MockWrite(ASYNC, 6,
2268 "GET / HTTP/1.1\r\n"
2269 "Host: www.example.org\r\n"
2270 "Connection: keep-alive\r\n"
2271 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2272 };
[email protected]2d2697f92009-02-18 21:00:322273
mmenkecc2298e2015-12-07 18:20:182274 MockRead data_reads[] = {
2275 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2276 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2277 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2278 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2279 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322280
mmenkecc2298e2015-12-07 18:20:182281 // Lastly, the server responds with the actual content.
2282 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2283 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2284 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2285 MockRead(ASYNC, 10, "Hello"),
2286 };
[email protected]2d2697f92009-02-18 21:00:322287
mmenkecc2298e2015-12-07 18:20:182288 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
2289 arraysize(data_writes));
2290 data.set_busy_before_sync_reads(true);
2291 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:462292
mmenkecc2298e2015-12-07 18:20:182293 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322294
mmenkecc2298e2015-12-07 18:20:182295 scoped_ptr<HttpTransaction> trans(
2296 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2297 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2298 ASSERT_EQ(OK, callback1.GetResult(rv));
[email protected]2d2697f92009-02-18 21:00:322299
mmenkecc2298e2015-12-07 18:20:182300 LoadTimingInfo load_timing_info1;
2301 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2302 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:322303
mmenkecc2298e2015-12-07 18:20:182304 const HttpResponseInfo* response = trans->GetResponseInfo();
2305 ASSERT_TRUE(response);
2306 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322307
mmenkecc2298e2015-12-07 18:20:182308 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:252309
mmenkecc2298e2015-12-07 18:20:182310 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
2311 callback2.callback());
2312 ASSERT_EQ(OK, callback2.GetResult(rv));
[email protected]2d2697f92009-02-18 21:00:322313
mmenkecc2298e2015-12-07 18:20:182314 LoadTimingInfo load_timing_info2;
2315 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2316 TestLoadTimingReused(load_timing_info2);
2317 // The load timing after restart should have the same socket ID, and times
2318 // those of the first load timing.
2319 EXPECT_LE(load_timing_info1.receive_headers_end,
2320 load_timing_info2.send_start);
2321 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:322322
mmenkecc2298e2015-12-07 18:20:182323 response = trans->GetResponseInfo();
2324 ASSERT_TRUE(response);
2325 EXPECT_FALSE(response->auth_challenge);
2326 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322327
mmenkecc2298e2015-12-07 18:20:182328 std::string response_data;
2329 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]2d2697f92009-02-18 21:00:322330
mmenkecc2298e2015-12-07 18:20:182331 int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes));
2332 EXPECT_EQ(writes_size, trans->GetTotalSentBytes());
2333 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
2334 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2335 }
[email protected]2d2697f92009-02-18 21:00:322336}
2337
2338// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2339// connection and with no response body to drain.
[email protected]23e482282013-06-14 16:08:022340TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:422341 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322342 request.method = "GET";
bncce36dca22015-04-21 22:11:232343 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322344 request.load_flags = 0;
2345
mmenkee65e7af2015-10-13 17:16:422346 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272347
[email protected]2d2697f92009-02-18 21:00:322348 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232349 MockWrite(
2350 "GET / HTTP/1.1\r\n"
2351 "Host: www.example.org\r\n"
2352 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322353
bncce36dca22015-04-21 22:11:232354 // After calling trans->RestartWithAuth(), this is the request we should
2355 // be issuing -- the final header line contains the credentials.
2356 MockWrite(
2357 "GET / HTTP/1.1\r\n"
2358 "Host: www.example.org\r\n"
2359 "Connection: keep-alive\r\n"
2360 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322361 };
2362
[email protected]2d2697f92009-02-18 21:00:322363 MockRead data_reads1[] = {
2364 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2365 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:312366 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:322367
2368 // Lastly, the server responds with the actual content.
2369 MockRead("HTTP/1.1 200 OK\r\n"),
2370 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502371 MockRead("Content-Length: 5\r\n\r\n"),
2372 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322373 };
2374
[email protected]2d0a4f92011-05-05 16:38:462375 // An incorrect reconnect would cause this to be read.
2376 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062377 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462378 };
2379
[email protected]31a2bfe2010-02-09 08:03:392380 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2381 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462382 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2383 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072384 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2385 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322386
[email protected]49639fa2011-12-20 23:22:412387 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322388
[email protected]262eec82013-03-19 21:01:362389 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502390 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412391 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422392 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322393
2394 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422395 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322396
[email protected]1c773ea12009-04-28 19:58:422397 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502398 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042399 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322400
[email protected]49639fa2011-12-20 23:22:412401 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322402
[email protected]49639fa2011-12-20 23:22:412403 rv = trans->RestartWithAuth(
2404 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422405 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322406
2407 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422408 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322409
2410 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502411 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322412 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502413 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322414}
2415
2416// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2417// connection and with a large response body to drain.
[email protected]23e482282013-06-14 16:08:022418TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:422419 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322420 request.method = "GET";
bncce36dca22015-04-21 22:11:232421 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322422 request.load_flags = 0;
2423
mmenkee65e7af2015-10-13 17:16:422424 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272425
[email protected]2d2697f92009-02-18 21:00:322426 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232427 MockWrite(
2428 "GET / HTTP/1.1\r\n"
2429 "Host: www.example.org\r\n"
2430 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322431
bncce36dca22015-04-21 22:11:232432 // After calling trans->RestartWithAuth(), this is the request we should
2433 // be issuing -- the final header line contains the credentials.
2434 MockWrite(
2435 "GET / HTTP/1.1\r\n"
2436 "Host: www.example.org\r\n"
2437 "Connection: keep-alive\r\n"
2438 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322439 };
2440
2441 // Respond with 5 kb of response body.
2442 std::string large_body_string("Unauthorized");
2443 large_body_string.append(5 * 1024, ' ');
2444 large_body_string.append("\r\n");
2445
2446 MockRead data_reads1[] = {
2447 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2448 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2449 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2450 // 5134 = 12 + 5 * 1024 + 2
2451 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062452 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:322453
2454 // Lastly, the server responds with the actual content.
2455 MockRead("HTTP/1.1 200 OK\r\n"),
2456 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502457 MockRead("Content-Length: 5\r\n\r\n"),
2458 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322459 };
2460
[email protected]2d0a4f92011-05-05 16:38:462461 // An incorrect reconnect would cause this to be read.
2462 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062463 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462464 };
2465
[email protected]31a2bfe2010-02-09 08:03:392466 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2467 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462468 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2469 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072470 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2471 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322472
[email protected]49639fa2011-12-20 23:22:412473 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322474
[email protected]262eec82013-03-19 21:01:362475 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502476 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412477 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422478 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322479
2480 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422481 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322482
[email protected]1c773ea12009-04-28 19:58:422483 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502484 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042485 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322486
[email protected]49639fa2011-12-20 23:22:412487 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322488
[email protected]49639fa2011-12-20 23:22:412489 rv = trans->RestartWithAuth(
2490 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422491 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322492
2493 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422494 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322495
2496 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502497 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322498 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502499 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322500}
2501
2502// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:312503// connection, but the server gets impatient and closes the connection.
[email protected]23e482282013-06-14 16:08:022504TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:312505 HttpRequestInfo request;
2506 request.method = "GET";
bncce36dca22015-04-21 22:11:232507 request.url = GURL("http://www.example.org/");
[email protected]11203f012009-11-12 23:02:312508 request.load_flags = 0;
2509
mmenkee65e7af2015-10-13 17:16:422510 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272511
[email protected]11203f012009-11-12 23:02:312512 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232513 MockWrite(
2514 "GET / HTTP/1.1\r\n"
2515 "Host: www.example.org\r\n"
2516 "Connection: keep-alive\r\n\r\n"),
2517 // This simulates the seemingly successful write to a closed connection
2518 // if the bug is not fixed.
2519 MockWrite(
2520 "GET / HTTP/1.1\r\n"
2521 "Host: www.example.org\r\n"
2522 "Connection: keep-alive\r\n"
2523 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312524 };
2525
2526 MockRead data_reads1[] = {
2527 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2528 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2529 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2530 MockRead("Content-Length: 14\r\n\r\n"),
2531 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:062532 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:312533 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:062534 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:312535 };
2536
2537 // After calling trans->RestartWithAuth(), this is the request we should
2538 // be issuing -- the final header line contains the credentials.
2539 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232540 MockWrite(
2541 "GET / HTTP/1.1\r\n"
2542 "Host: www.example.org\r\n"
2543 "Connection: keep-alive\r\n"
2544 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312545 };
2546
2547 // Lastly, the server responds with the actual content.
2548 MockRead data_reads2[] = {
2549 MockRead("HTTP/1.1 200 OK\r\n"),
2550 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502551 MockRead("Content-Length: 5\r\n\r\n"),
2552 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:312553 };
2554
[email protected]31a2bfe2010-02-09 08:03:392555 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2556 data_writes1, arraysize(data_writes1));
2557 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2558 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:072559 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2560 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:312561
[email protected]49639fa2011-12-20 23:22:412562 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:312563
[email protected]262eec82013-03-19 21:01:362564 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502565 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412566 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]11203f012009-11-12 23:02:312567 EXPECT_EQ(ERR_IO_PENDING, rv);
2568
2569 rv = callback1.WaitForResult();
2570 EXPECT_EQ(OK, rv);
2571
2572 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502573 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042574 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]11203f012009-11-12 23:02:312575
[email protected]49639fa2011-12-20 23:22:412576 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:312577
[email protected]49639fa2011-12-20 23:22:412578 rv = trans->RestartWithAuth(
2579 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]11203f012009-11-12 23:02:312580 EXPECT_EQ(ERR_IO_PENDING, rv);
2581
2582 rv = callback2.WaitForResult();
2583 EXPECT_EQ(OK, rv);
2584
2585 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502586 ASSERT_TRUE(response != NULL);
[email protected]11203f012009-11-12 23:02:312587 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502588 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:312589}
2590
[email protected]394816e92010-08-03 07:38:592591// Test the request-challenge-retry sequence for basic auth, over a connection
2592// that requires a restart when setting up an SSL tunnel.
ttuttle34f63b52015-03-05 04:33:012593TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
2594 HttpRequestInfo request;
2595 request.method = "GET";
bncce36dca22015-04-21 22:11:232596 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:012597 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292598 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:012599
2600 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032601 session_deps_.proxy_service =
2602 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512603 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:012604 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:422605 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:012606
2607 // Since we have proxy, should try to establish tunnel.
2608 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542609 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172610 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542611 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:012612 };
2613
mmenkee71e15332015-10-07 16:39:542614 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:012615 // connection.
2616 MockRead data_reads1[] = {
2617 // No credentials.
2618 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2619 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:542620 };
ttuttle34f63b52015-03-05 04:33:012621
mmenkee71e15332015-10-07 16:39:542622 // Since the first connection couldn't be reused, need to establish another
2623 // once given credentials.
2624 MockWrite data_writes2[] = {
2625 // After calling trans->RestartWithAuth(), this is the request we should
2626 // be issuing -- the final header line contains the credentials.
2627 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172628 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542629 "Proxy-Connection: keep-alive\r\n"
2630 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2631
2632 MockWrite("GET / HTTP/1.1\r\n"
2633 "Host: www.example.org\r\n"
2634 "Connection: keep-alive\r\n\r\n"),
2635 };
2636
2637 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:012638 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2639
2640 MockRead("HTTP/1.1 200 OK\r\n"),
2641 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2642 MockRead("Content-Length: 5\r\n\r\n"),
2643 MockRead(SYNCHRONOUS, "hello"),
2644 };
2645
2646 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2647 data_writes1, arraysize(data_writes1));
2648 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542649 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2650 data_writes2, arraysize(data_writes2));
2651 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:012652 SSLSocketDataProvider ssl(ASYNC, OK);
2653 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2654
2655 TestCompletionCallback callback1;
2656
2657 scoped_ptr<HttpTransaction> trans(
2658 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2659
2660 int rv = trans->Start(&request, callback1.callback(), log.bound());
2661 EXPECT_EQ(ERR_IO_PENDING, rv);
2662
2663 rv = callback1.WaitForResult();
2664 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462665 TestNetLogEntry::List entries;
ttuttle34f63b52015-03-05 04:33:012666 log.GetEntries(&entries);
2667 size_t pos = ExpectLogContainsSomewhere(
2668 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2669 NetLog::PHASE_NONE);
2670 ExpectLogContainsSomewhere(
2671 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2672 NetLog::PHASE_NONE);
2673
2674 const HttpResponseInfo* response = trans->GetResponseInfo();
2675 ASSERT_TRUE(response != NULL);
2676 EXPECT_FALSE(response->headers->IsKeepAlive());
2677 ASSERT_FALSE(response->headers.get() == NULL);
2678 EXPECT_EQ(407, response->headers->response_code());
2679 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2680 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2681
2682 LoadTimingInfo load_timing_info;
2683 // CONNECT requests and responses are handled at the connect job level, so
2684 // the transaction does not yet have a connection.
2685 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2686
2687 TestCompletionCallback callback2;
2688
2689 rv =
2690 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
2691 EXPECT_EQ(ERR_IO_PENDING, rv);
2692
2693 rv = callback2.WaitForResult();
2694 EXPECT_EQ(OK, rv);
2695
2696 response = trans->GetResponseInfo();
2697 ASSERT_TRUE(response != NULL);
2698
2699 EXPECT_TRUE(response->headers->IsKeepAlive());
2700 EXPECT_EQ(200, response->headers->response_code());
2701 EXPECT_EQ(5, response->headers->GetContentLength());
2702 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2703
2704 // The password prompt info should not be set.
2705 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2706
2707 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2708 TestLoadTimingNotReusedWithPac(load_timing_info,
2709 CONNECT_TIMING_HAS_SSL_TIMES);
2710
2711 trans.reset();
2712 session->CloseAllConnections();
2713}
2714
2715// Test the request-challenge-retry sequence for basic auth, over a connection
2716// that requires a restart when setting up an SSL tunnel.
2717TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:592718 HttpRequestInfo request;
2719 request.method = "GET";
bncce36dca22015-04-21 22:11:232720 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:592721 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292722 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]394816e92010-08-03 07:38:592723
[email protected]cb9bf6ca2011-01-28 13:15:272724 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032725 session_deps_.proxy_service =
2726 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512727 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072728 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:422729 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272730
[email protected]394816e92010-08-03 07:38:592731 // Since we have proxy, should try to establish tunnel.
2732 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542733 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172734 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542735 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:112736 };
2737
mmenkee71e15332015-10-07 16:39:542738 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:082739 // connection.
2740 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:542741 // No credentials.
2742 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2743 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2744 MockRead("Proxy-Connection: close\r\n\r\n"),
2745 };
mmenkee0b5c882015-08-26 20:29:112746
mmenkee71e15332015-10-07 16:39:542747 MockWrite data_writes2[] = {
2748 // After calling trans->RestartWithAuth(), this is the request we should
2749 // be issuing -- the final header line contains the credentials.
2750 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172751 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542752 "Proxy-Connection: keep-alive\r\n"
2753 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:082754
mmenkee71e15332015-10-07 16:39:542755 MockWrite("GET / HTTP/1.1\r\n"
2756 "Host: www.example.org\r\n"
2757 "Connection: keep-alive\r\n\r\n"),
2758 };
2759
2760 MockRead data_reads2[] = {
2761 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2762
2763 MockRead("HTTP/1.1 200 OK\r\n"),
2764 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2765 MockRead("Content-Length: 5\r\n\r\n"),
2766 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:592767 };
2768
2769 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2770 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:072771 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542772 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2773 data_writes2, arraysize(data_writes2));
2774 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:062775 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:072776 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:592777
[email protected]49639fa2011-12-20 23:22:412778 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:592779
[email protected]262eec82013-03-19 21:01:362780 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502781 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:502782
[email protected]49639fa2011-12-20 23:22:412783 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]394816e92010-08-03 07:38:592784 EXPECT_EQ(ERR_IO_PENDING, rv);
2785
2786 rv = callback1.WaitForResult();
2787 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462788 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:402789 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:592790 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402791 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:592792 NetLog::PHASE_NONE);
2793 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402794 entries, pos,
[email protected]394816e92010-08-03 07:38:592795 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2796 NetLog::PHASE_NONE);
2797
2798 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502799 ASSERT_TRUE(response != NULL);
ttuttle34f63b52015-03-05 04:33:012800 EXPECT_FALSE(response->headers->IsKeepAlive());
[email protected]90499482013-06-01 00:39:502801 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]394816e92010-08-03 07:38:592802 EXPECT_EQ(407, response->headers->response_code());
2803 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042804 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]394816e92010-08-03 07:38:592805
[email protected]029c83b62013-01-24 05:28:202806 LoadTimingInfo load_timing_info;
2807 // CONNECT requests and responses are handled at the connect job level, so
2808 // the transaction does not yet have a connection.
2809 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2810
[email protected]49639fa2011-12-20 23:22:412811 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:592812
[email protected]49639fa2011-12-20 23:22:412813 rv = trans->RestartWithAuth(
2814 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]394816e92010-08-03 07:38:592815 EXPECT_EQ(ERR_IO_PENDING, rv);
2816
2817 rv = callback2.WaitForResult();
2818 EXPECT_EQ(OK, rv);
2819
2820 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502821 ASSERT_TRUE(response != NULL);
[email protected]394816e92010-08-03 07:38:592822
2823 EXPECT_TRUE(response->headers->IsKeepAlive());
2824 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:502825 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:592826 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2827
2828 // The password prompt info should not be set.
2829 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502830
[email protected]029c83b62013-01-24 05:28:202831 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2832 TestLoadTimingNotReusedWithPac(load_timing_info,
2833 CONNECT_TIMING_HAS_SSL_TIMES);
2834
[email protected]0b0bf032010-09-21 18:08:502835 trans.reset();
[email protected]102e27c2011-02-23 01:01:312836 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:592837}
2838
[email protected]11203f012009-11-12 23:02:312839// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:012840// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2841TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:232842 // On the second pass, the body read of the auth challenge is synchronous, so
2843 // IsConnectedAndIdle returns false. The socket should still be drained and
2844 // reused. See http://crbug.com/544255.
2845 for (int i = 0; i < 2; ++i) {
2846 HttpRequestInfo request;
2847 request.method = "GET";
2848 request.url = GURL("https://www.example.org/");
2849 // Ensure that proxy authentication is attempted even
2850 // when the no authentication data flag is set.
2851 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:012852
mmenked39192ee2015-12-09 00:57:232853 // Configure against proxy server "myproxy:70".
2854 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
2855 BoundTestNetLog log;
2856 session_deps_.net_log = log.bound().net_log();
2857 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:012858
mmenked39192ee2015-12-09 00:57:232859 scoped_ptr<HttpTransaction> trans(
2860 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
ttuttle34f63b52015-03-05 04:33:012861
mmenked39192ee2015-12-09 00:57:232862 // Since we have proxy, should try to establish tunnel.
2863 MockWrite data_writes1[] = {
2864 MockWrite(ASYNC, 0,
2865 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2866 "Host: www.example.org:443\r\n"
2867 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:012868
mmenked39192ee2015-12-09 00:57:232869 // After calling trans->RestartWithAuth(), this is the request we should
2870 // be issuing -- the final header line contains the credentials.
2871 MockWrite(ASYNC, 3,
2872 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2873 "Host: www.example.org:443\r\n"
2874 "Proxy-Connection: keep-alive\r\n"
2875 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2876 };
ttuttle34f63b52015-03-05 04:33:012877
mmenked39192ee2015-12-09 00:57:232878 // The proxy responds to the connect with a 407, using a persistent
2879 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2880 MockRead data_reads1[] = {
2881 // No credentials.
2882 MockRead(ASYNC, 1,
2883 "HTTP/1.0 407 Proxy Authentication Required\r\n"
2884 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
2885 "Proxy-Connection: keep-alive\r\n"
2886 "Content-Length: 10\r\n\r\n"),
2887 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:012888
mmenked39192ee2015-12-09 00:57:232889 // Wrong credentials (wrong password).
2890 MockRead(ASYNC, 4,
2891 "HTTP/1.0 407 Proxy Authentication Required\r\n"
2892 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
2893 "Proxy-Connection: keep-alive\r\n"
2894 "Content-Length: 10\r\n\r\n"),
2895 // No response body because the test stops reading here.
2896 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
2897 };
ttuttle34f63b52015-03-05 04:33:012898
mmenked39192ee2015-12-09 00:57:232899 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
2900 arraysize(data_writes1));
2901 data1.set_busy_before_sync_reads(true);
2902 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:012903
mmenked39192ee2015-12-09 00:57:232904 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:012905
mmenked39192ee2015-12-09 00:57:232906 int rv = trans->Start(&request, callback1.callback(), log.bound());
2907 EXPECT_EQ(OK, callback1.GetResult(rv));
ttuttle34f63b52015-03-05 04:33:012908
mmenked39192ee2015-12-09 00:57:232909 TestNetLogEntry::List entries;
2910 log.GetEntries(&entries);
2911 size_t pos = ExpectLogContainsSomewhere(
2912 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2913 NetLog::PHASE_NONE);
2914 ExpectLogContainsSomewhere(
2915 entries, pos,
2916 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2917 NetLog::PHASE_NONE);
ttuttle34f63b52015-03-05 04:33:012918
mmenked39192ee2015-12-09 00:57:232919 const HttpResponseInfo* response = trans->GetResponseInfo();
2920 ASSERT_TRUE(response);
2921 ASSERT_TRUE(response->headers);
2922 EXPECT_TRUE(response->headers->IsKeepAlive());
2923 EXPECT_EQ(407, response->headers->response_code());
2924 EXPECT_EQ(10, response->headers->GetContentLength());
2925 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2926 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
ttuttle34f63b52015-03-05 04:33:012927
mmenked39192ee2015-12-09 00:57:232928 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:012929
mmenked39192ee2015-12-09 00:57:232930 // Wrong password (should be "bar").
2931 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBaz),
2932 callback2.callback());
2933 EXPECT_EQ(OK, callback2.GetResult(rv));
ttuttle34f63b52015-03-05 04:33:012934
mmenked39192ee2015-12-09 00:57:232935 response = trans->GetResponseInfo();
2936 ASSERT_TRUE(response);
2937 ASSERT_TRUE(response->headers);
2938 EXPECT_TRUE(response->headers->IsKeepAlive());
2939 EXPECT_EQ(407, response->headers->response_code());
2940 EXPECT_EQ(10, response->headers->GetContentLength());
2941 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2942 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
ttuttle34f63b52015-03-05 04:33:012943
mmenked39192ee2015-12-09 00:57:232944 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2945 // out of scope.
2946 session->CloseAllConnections();
2947 }
ttuttle34f63b52015-03-05 04:33:012948}
2949
2950// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2951// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2952TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:232953 // On the second pass, the body read of the auth challenge is synchronous, so
2954 // IsConnectedAndIdle returns false. The socket should still be drained and
2955 // reused. See http://crbug.com/544255.
2956 for (int i = 0; i < 2; ++i) {
2957 HttpRequestInfo request;
2958 request.method = "GET";
2959 request.url = GURL("https://www.example.org/");
2960 // Ensure that proxy authentication is attempted even
2961 // when the no authentication data flag is set.
2962 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2963
2964 // Configure against proxy server "myproxy:70".
2965 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
2966 BoundTestNetLog log;
2967 session_deps_.net_log = log.bound().net_log();
2968 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2969
2970 scoped_ptr<HttpTransaction> trans(
2971 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2972
2973 // Since we have proxy, should try to establish tunnel.
2974 MockWrite data_writes1[] = {
2975 MockWrite(ASYNC, 0,
2976 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2977 "Host: www.example.org:443\r\n"
2978 "Proxy-Connection: keep-alive\r\n\r\n"),
2979
2980 // After calling trans->RestartWithAuth(), this is the request we should
2981 // be issuing -- the final header line contains the credentials.
2982 MockWrite(ASYNC, 3,
2983 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2984 "Host: www.example.org:443\r\n"
2985 "Proxy-Connection: keep-alive\r\n"
2986 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2987 };
2988
2989 // The proxy responds to the connect with a 407, using a persistent
2990 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2991 MockRead data_reads1[] = {
2992 // No credentials.
2993 MockRead(ASYNC, 1,
2994 "HTTP/1.1 407 Proxy Authentication Required\r\n"
2995 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
2996 "Content-Length: 10\r\n\r\n"),
2997 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
2998
2999 // Wrong credentials (wrong password).
3000 MockRead(ASYNC, 4,
3001 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3002 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3003 "Content-Length: 10\r\n\r\n"),
3004 // No response body because the test stops reading here.
3005 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3006 };
3007
3008 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
3009 arraysize(data_writes1));
3010 data1.set_busy_before_sync_reads(true);
3011 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3012
3013 TestCompletionCallback callback1;
3014
3015 int rv = trans->Start(&request, callback1.callback(), log.bound());
3016 EXPECT_EQ(OK, callback1.GetResult(rv));
3017
3018 TestNetLogEntry::List entries;
3019 log.GetEntries(&entries);
3020 size_t pos = ExpectLogContainsSomewhere(
3021 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3022 NetLog::PHASE_NONE);
3023 ExpectLogContainsSomewhere(
3024 entries, pos,
3025 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3026 NetLog::PHASE_NONE);
3027
3028 const HttpResponseInfo* response = trans->GetResponseInfo();
3029 ASSERT_TRUE(response);
3030 ASSERT_TRUE(response->headers);
3031 EXPECT_TRUE(response->headers->IsKeepAlive());
3032 EXPECT_EQ(407, response->headers->response_code());
3033 EXPECT_EQ(10, response->headers->GetContentLength());
3034 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3035 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3036
3037 TestCompletionCallback callback2;
3038
3039 // Wrong password (should be "bar").
3040 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBaz),
3041 callback2.callback());
3042 EXPECT_EQ(OK, callback2.GetResult(rv));
3043
3044 response = trans->GetResponseInfo();
3045 ASSERT_TRUE(response);
3046 ASSERT_TRUE(response->headers);
3047 EXPECT_TRUE(response->headers->IsKeepAlive());
3048 EXPECT_EQ(407, response->headers->response_code());
3049 EXPECT_EQ(10, response->headers->GetContentLength());
3050 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3051 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3052
3053 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3054 // out of scope.
3055 session->CloseAllConnections();
3056 }
3057}
3058
3059// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3060// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3061// the case the server sends extra data on the original socket, so it can't be
3062// reused.
3063TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273064 HttpRequestInfo request;
3065 request.method = "GET";
bncce36dca22015-04-21 22:11:233066 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273067 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293068 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]cb9bf6ca2011-01-28 13:15:273069
[email protected]2d2697f92009-02-18 21:00:323070 // Configure against proxy server "myproxy:70".
mmenked39192ee2015-12-09 00:57:233071 session_deps_.proxy_service =
3072 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:513073 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073074 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423075 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323076
[email protected]2d2697f92009-02-18 21:00:323077 // Since we have proxy, should try to establish tunnel.
3078 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233079 MockWrite(ASYNC, 0,
3080 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173081 "Host: www.example.org:443\r\n"
3082 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233083 };
[email protected]2d2697f92009-02-18 21:00:323084
mmenked39192ee2015-12-09 00:57:233085 // The proxy responds to the connect with a 407, using a persistent, but sends
3086 // extra data, so the socket cannot be reused.
3087 MockRead data_reads1[] = {
3088 // No credentials.
3089 MockRead(ASYNC, 1,
3090 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3091 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3092 "Content-Length: 10\r\n\r\n"),
3093 MockRead(SYNCHRONOUS, 2, "0123456789"),
3094 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3095 };
3096
3097 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233098 // After calling trans->RestartWithAuth(), this is the request we should
3099 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233100 MockWrite(ASYNC, 0,
3101 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173102 "Host: www.example.org:443\r\n"
3103 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233104 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3105
3106 MockWrite(ASYNC, 2,
3107 "GET / HTTP/1.1\r\n"
3108 "Host: www.example.org\r\n"
3109 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323110 };
3111
mmenked39192ee2015-12-09 00:57:233112 MockRead data_reads2[] = {
3113 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323114
mmenked39192ee2015-12-09 00:57:233115 MockRead(ASYNC, 3,
3116 "HTTP/1.1 200 OK\r\n"
3117 "Content-Type: text/html; charset=iso-8859-1\r\n"
3118 "Content-Length: 5\r\n\r\n"),
3119 // No response body because the test stops reading here.
3120 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323121 };
3122
mmenked39192ee2015-12-09 00:57:233123 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
3124 arraysize(data_writes1));
3125 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073126 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenked39192ee2015-12-09 00:57:233127 SequencedSocketData data2(data_reads2, arraysize(data_reads2), data_writes2,
3128 arraysize(data_writes2));
3129 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3130 SSLSocketDataProvider ssl(ASYNC, OK);
3131 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323132
[email protected]49639fa2011-12-20 23:22:413133 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323134
mmenked39192ee2015-12-09 00:57:233135 scoped_ptr<HttpTransaction> trans(
3136 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d2697f92009-02-18 21:00:323137
mmenked39192ee2015-12-09 00:57:233138 int rv = trans->Start(&request, callback1.callback(), log.bound());
3139 EXPECT_EQ(OK, callback1.GetResult(rv));
3140
mmenke43758e62015-05-04 21:09:463141 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403142 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:393143 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403144 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:393145 NetLog::PHASE_NONE);
3146 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403147 entries, pos,
[email protected]dbb83db2010-05-11 18:13:393148 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3149 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:323150
[email protected]1c773ea12009-04-28 19:58:423151 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243152 ASSERT_TRUE(response);
3153 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323154 EXPECT_TRUE(response->headers->IsKeepAlive());
3155 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423156 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:043157 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:323158
mmenked39192ee2015-12-09 00:57:233159 LoadTimingInfo load_timing_info;
3160 // CONNECT requests and responses are handled at the connect job level, so
3161 // the transaction does not yet have a connection.
3162 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3163
[email protected]49639fa2011-12-20 23:22:413164 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323165
mmenked39192ee2015-12-09 00:57:233166 rv =
3167 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
3168 EXPECT_EQ(OK, callback2.GetResult(rv));
[email protected]2d2697f92009-02-18 21:00:323169
[email protected]2d2697f92009-02-18 21:00:323170 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233171 EXPECT_EQ(200, response->headers->response_code());
3172 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423173 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133174
mmenked39192ee2015-12-09 00:57:233175 // The password prompt info should not be set.
3176 EXPECT_FALSE(response->auth_challenge);
3177
3178 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3179 TestLoadTimingNotReusedWithPac(load_timing_info,
3180 CONNECT_TIMING_HAS_SSL_TIMES);
3181
3182 trans.reset();
[email protected]102e27c2011-02-23 01:01:313183 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323184}
3185
mmenkee71e15332015-10-07 16:39:543186// Test the case a proxy closes a socket while the challenge body is being
3187// drained.
3188TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
3189 HttpRequestInfo request;
3190 request.method = "GET";
3191 request.url = GURL("https://www.example.org/");
3192 // Ensure that proxy authentication is attempted even
3193 // when the no authentication data flag is set.
3194 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
3195
3196 // Configure against proxy server "myproxy:70".
3197 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:423198 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543199
3200 scoped_ptr<HttpTransaction> trans(
3201 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3202
3203 // Since we have proxy, should try to establish tunnel.
3204 MockWrite data_writes1[] = {
3205 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173206 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543207 "Proxy-Connection: keep-alive\r\n\r\n"),
3208 };
3209
3210 // The proxy responds to the connect with a 407, using a persistent
3211 // connection.
3212 MockRead data_reads1[] = {
3213 // No credentials.
3214 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3215 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3216 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3217 // Server hands up in the middle of the body.
3218 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3219 };
3220
3221 MockWrite data_writes2[] = {
3222 // After calling trans->RestartWithAuth(), this is the request we should
3223 // be issuing -- the final header line contains the credentials.
3224 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173225 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543226 "Proxy-Connection: keep-alive\r\n"
3227 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3228
3229 MockWrite("GET / HTTP/1.1\r\n"
3230 "Host: www.example.org\r\n"
3231 "Connection: keep-alive\r\n\r\n"),
3232 };
3233
3234 MockRead data_reads2[] = {
3235 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3236
3237 MockRead("HTTP/1.1 200 OK\r\n"),
3238 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3239 MockRead("Content-Length: 5\r\n\r\n"),
3240 MockRead(SYNCHRONOUS, "hello"),
3241 };
3242
3243 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3244 data_writes1, arraysize(data_writes1));
3245 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3246 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3247 data_writes2, arraysize(data_writes2));
3248 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3249 SSLSocketDataProvider ssl(ASYNC, OK);
3250 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3251
3252 TestCompletionCallback callback;
3253
3254 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3255 EXPECT_EQ(OK, callback.GetResult(rv));
3256
3257 const HttpResponseInfo* response = trans->GetResponseInfo();
3258 ASSERT_TRUE(response);
3259 ASSERT_TRUE(response->headers);
3260 EXPECT_TRUE(response->headers->IsKeepAlive());
3261 EXPECT_EQ(407, response->headers->response_code());
3262 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3263
3264 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
3265 EXPECT_EQ(OK, callback.GetResult(rv));
3266
3267 response = trans->GetResponseInfo();
3268 ASSERT_TRUE(response);
3269 ASSERT_TRUE(response->headers);
3270 EXPECT_TRUE(response->headers->IsKeepAlive());
3271 EXPECT_EQ(200, response->headers->response_code());
3272 std::string body;
3273 EXPECT_EQ(OK, ReadTransaction(trans.get(), &body));
3274 EXPECT_EQ("hello", body);
3275}
3276
[email protected]a8e9b162009-03-12 00:06:443277// Test that we don't read the response body when we fail to establish a tunnel,
3278// even if the user cancels the proxy's auth attempt.
[email protected]23e482282013-06-14 16:08:023279TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273280 HttpRequestInfo request;
3281 request.method = "GET";
bncce36dca22015-04-21 22:11:233282 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273283 request.load_flags = 0;
3284
[email protected]a8e9b162009-03-12 00:06:443285 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033286 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]a8e9b162009-03-12 00:06:443287
mmenkee65e7af2015-10-13 17:16:423288 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443289
[email protected]262eec82013-03-19 21:01:363290 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503291 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]a8e9b162009-03-12 00:06:443292
[email protected]a8e9b162009-03-12 00:06:443293 // Since we have proxy, should try to establish tunnel.
3294 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173295 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3296 "Host: www.example.org:443\r\n"
3297 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443298 };
3299
3300 // The proxy responds to the connect with a 407.
3301 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243302 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3303 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3304 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233305 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:243306 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443307 };
3308
[email protected]31a2bfe2010-02-09 08:03:393309 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3310 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:073311 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443312
[email protected]49639fa2011-12-20 23:22:413313 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443314
[email protected]49639fa2011-12-20 23:22:413315 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423316 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:443317
3318 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423319 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:443320
[email protected]1c773ea12009-04-28 19:58:423321 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243322 ASSERT_TRUE(response);
3323 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:443324 EXPECT_TRUE(response->headers->IsKeepAlive());
3325 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423326 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:443327
3328 std::string response_data;
3329 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423330 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:183331
3332 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:313333 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:443334}
3335
ttuttle7933c112015-01-06 00:55:243336// Test that we don't pass extraneous headers from the proxy's response to the
3337// caller when the proxy responds to CONNECT with 407.
3338TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
3339 HttpRequestInfo request;
3340 request.method = "GET";
bncce36dca22015-04-21 22:11:233341 request.url = GURL("https://www.example.org/");
ttuttle7933c112015-01-06 00:55:243342 request.load_flags = 0;
3343
3344 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033345 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
ttuttle7933c112015-01-06 00:55:243346
mmenkee65e7af2015-10-13 17:16:423347 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:243348
3349 scoped_ptr<HttpTransaction> trans(
3350 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3351
3352 // Since we have proxy, should try to establish tunnel.
3353 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173354 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3355 "Host: www.example.org:443\r\n"
3356 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:243357 };
3358
3359 // The proxy responds to the connect with a 407.
3360 MockRead data_reads[] = {
3361 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3362 MockRead("X-Foo: bar\r\n"),
3363 MockRead("Set-Cookie: foo=bar\r\n"),
3364 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3365 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233366 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:243367 };
3368
3369 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
3370 arraysize(data_writes));
3371 session_deps_.socket_factory->AddSocketDataProvider(&data);
3372
3373 TestCompletionCallback callback;
3374
3375 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3376 EXPECT_EQ(ERR_IO_PENDING, rv);
3377
3378 rv = callback.WaitForResult();
3379 EXPECT_EQ(OK, rv);
3380
3381 const HttpResponseInfo* response = trans->GetResponseInfo();
3382 ASSERT_TRUE(response);
3383 ASSERT_TRUE(response->headers);
3384 EXPECT_TRUE(response->headers->IsKeepAlive());
3385 EXPECT_EQ(407, response->headers->response_code());
3386 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3387 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
3388 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
3389
3390 std::string response_data;
3391 rv = ReadTransaction(trans.get(), &response_data);
3392 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3393
3394 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3395 session->CloseAllConnections();
3396}
3397
[email protected]8fdbcd22010-05-05 02:54:523398// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
3399// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
[email protected]23e482282013-06-14 16:08:023400TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:523401 HttpRequestInfo request;
3402 request.method = "GET";
bncce36dca22015-04-21 22:11:233403 request.url = GURL("http://www.example.org/");
[email protected]8fdbcd22010-05-05 02:54:523404 request.load_flags = 0;
3405
[email protected]cb9bf6ca2011-01-28 13:15:273406 // We are using a DIRECT connection (i.e. no proxy) for this session.
mmenkee65e7af2015-10-13 17:16:423407 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273408 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:413409 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:273410
[email protected]8fdbcd22010-05-05 02:54:523411 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233412 MockWrite(
3413 "GET / HTTP/1.1\r\n"
3414 "Host: www.example.org\r\n"
3415 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:523416 };
3417
3418 MockRead data_reads1[] = {
3419 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
3420 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3421 // Large content-length -- won't matter, as connection will be reset.
3422 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063423 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:523424 };
3425
3426 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3427 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073428 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:523429
[email protected]49639fa2011-12-20 23:22:413430 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:523431
[email protected]49639fa2011-12-20 23:22:413432 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]8fdbcd22010-05-05 02:54:523433 EXPECT_EQ(ERR_IO_PENDING, rv);
3434
3435 rv = callback.WaitForResult();
3436 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3437}
3438
[email protected]7a67a8152010-11-05 18:31:103439// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3440// through a non-authenticating proxy. The request should fail with
3441// ERR_UNEXPECTED_PROXY_AUTH.
3442// Note that it is impossible to detect if an HTTP server returns a 407 through
3443// a non-authenticating proxy - there is nothing to indicate whether the
3444// response came from the proxy or the server, so it is treated as if the proxy
3445// issued the challenge.
[email protected]23e482282013-06-14 16:08:023446TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:233447 HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:273448 HttpRequestInfo request;
3449 request.method = "GET";
bncce36dca22015-04-21 22:11:233450 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273451
rdsmith82957ad2015-09-16 19:42:033452 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:513453 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073454 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423455 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:103456
[email protected]7a67a8152010-11-05 18:31:103457 // Since we have proxy, should try to establish tunnel.
3458 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:173459 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3460 "Host: www.example.org:443\r\n"
3461 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103462
rsleevidb16bb02015-11-12 23:47:173463 MockWrite("GET / HTTP/1.1\r\n"
3464 "Host: www.example.org\r\n"
3465 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103466 };
3467
3468 MockRead data_reads1[] = {
3469 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3470
3471 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3472 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3473 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:063474 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:103475 };
3476
3477 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3478 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073479 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:063480 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073481 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:103482
[email protected]49639fa2011-12-20 23:22:413483 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:103484
[email protected]262eec82013-03-19 21:01:363485 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503486 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a67a8152010-11-05 18:31:103487
[email protected]49639fa2011-12-20 23:22:413488 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7a67a8152010-11-05 18:31:103489 EXPECT_EQ(ERR_IO_PENDING, rv);
3490
3491 rv = callback1.WaitForResult();
3492 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
mmenke43758e62015-05-04 21:09:463493 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403494 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:103495 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403496 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:103497 NetLog::PHASE_NONE);
3498 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403499 entries, pos,
[email protected]7a67a8152010-11-05 18:31:103500 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3501 NetLog::PHASE_NONE);
3502}
[email protected]2df19bb2010-08-25 20:13:463503
mmenke2a1781d2015-10-07 19:25:333504// Test a proxy auth scheme that allows default credentials and a proxy server
3505// that uses non-persistent connections.
3506TEST_P(HttpNetworkTransactionTest,
3507 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
3508 HttpRequestInfo request;
3509 request.method = "GET";
3510 request.url = GURL("https://www.example.org/");
3511
3512 // Configure against proxy server "myproxy:70".
3513 session_deps_.proxy_service =
3514 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3515
3516 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3517 new HttpAuthHandlerMock::Factory());
3518 auth_handler_factory->set_do_init_from_challenge(true);
3519 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3520 mock_handler->set_allows_default_credentials(true);
3521 auth_handler_factory->AddMockHandler(mock_handler.release(),
3522 HttpAuth::AUTH_PROXY);
3523 session_deps_.http_auth_handler_factory = auth_handler_factory.Pass();
3524
3525 // Add NetLog just so can verify load timing information gets a NetLog ID.
3526 NetLog net_log;
3527 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423528 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333529
3530 // Since we have proxy, should try to establish tunnel.
3531 MockWrite data_writes1[] = {
3532 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173533 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333534 "Proxy-Connection: keep-alive\r\n\r\n"),
3535 };
3536
3537 // The proxy responds to the connect with a 407, using a non-persistent
3538 // connection.
3539 MockRead data_reads1[] = {
3540 // No credentials.
3541 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3542 MockRead("Proxy-Authenticate: Mock\r\n"),
3543 MockRead("Proxy-Connection: close\r\n\r\n"),
3544 };
3545
3546 // Since the first connection couldn't be reused, need to establish another
3547 // once given credentials.
3548 MockWrite data_writes2[] = {
3549 // After calling trans->RestartWithAuth(), this is the request we should
3550 // be issuing -- the final header line contains the credentials.
3551 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173552 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333553 "Proxy-Connection: keep-alive\r\n"
3554 "Proxy-Authorization: auth_token\r\n\r\n"),
3555
3556 MockWrite("GET / HTTP/1.1\r\n"
3557 "Host: www.example.org\r\n"
3558 "Connection: keep-alive\r\n\r\n"),
3559 };
3560
3561 MockRead data_reads2[] = {
3562 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3563
3564 MockRead("HTTP/1.1 200 OK\r\n"),
3565 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3566 MockRead("Content-Length: 5\r\n\r\n"),
3567 MockRead(SYNCHRONOUS, "hello"),
3568 };
3569
3570 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3571 data_writes1, arraysize(data_writes1));
3572 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3573 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3574 data_writes2, arraysize(data_writes2));
3575 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3576 SSLSocketDataProvider ssl(ASYNC, OK);
3577 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3578
3579 scoped_ptr<HttpTransaction> trans(
3580 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3581
3582 TestCompletionCallback callback;
3583 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3584 EXPECT_EQ(OK, callback.GetResult(rv));
3585
3586 const HttpResponseInfo* response = trans->GetResponseInfo();
3587 ASSERT_TRUE(response);
3588 ASSERT_TRUE(response->headers);
3589 EXPECT_FALSE(response->headers->IsKeepAlive());
3590 EXPECT_EQ(407, response->headers->response_code());
3591 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3592 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3593 EXPECT_FALSE(response->auth_challenge.get());
3594
3595 LoadTimingInfo load_timing_info;
3596 // CONNECT requests and responses are handled at the connect job level, so
3597 // the transaction does not yet have a connection.
3598 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3599
3600 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3601 EXPECT_EQ(OK, callback.GetResult(rv));
3602 response = trans->GetResponseInfo();
3603 ASSERT_TRUE(response);
3604 ASSERT_TRUE(response->headers);
3605 EXPECT_TRUE(response->headers->IsKeepAlive());
3606 EXPECT_EQ(200, response->headers->response_code());
3607 EXPECT_EQ(5, response->headers->GetContentLength());
3608 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3609
3610 // The password prompt info should not be set.
3611 EXPECT_FALSE(response->auth_challenge);
3612
3613 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3614 TestLoadTimingNotReusedWithPac(load_timing_info,
3615 CONNECT_TIMING_HAS_SSL_TIMES);
3616
3617 trans.reset();
3618 session->CloseAllConnections();
3619}
3620
3621// Test a proxy auth scheme that allows default credentials and a proxy server
3622// that hangs up when credentials are initially sent.
3623TEST_P(HttpNetworkTransactionTest,
3624 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
3625 HttpRequestInfo request;
3626 request.method = "GET";
3627 request.url = GURL("https://www.example.org/");
3628
3629 // Configure against proxy server "myproxy:70".
3630 session_deps_.proxy_service =
3631 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3632
3633 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3634 new HttpAuthHandlerMock::Factory());
3635 auth_handler_factory->set_do_init_from_challenge(true);
3636 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3637 mock_handler->set_allows_default_credentials(true);
3638 auth_handler_factory->AddMockHandler(mock_handler.release(),
3639 HttpAuth::AUTH_PROXY);
3640 session_deps_.http_auth_handler_factory = auth_handler_factory.Pass();
3641
3642 // Add NetLog just so can verify load timing information gets a NetLog ID.
3643 NetLog net_log;
3644 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423645 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333646
3647 // Should try to establish tunnel.
3648 MockWrite data_writes1[] = {
3649 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173650 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333651 "Proxy-Connection: keep-alive\r\n\r\n"),
3652
3653 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173654 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333655 "Proxy-Connection: keep-alive\r\n"
3656 "Proxy-Authorization: auth_token\r\n\r\n"),
3657 };
3658
3659 // The proxy responds to the connect with a 407, using a non-persistent
3660 // connection.
3661 MockRead data_reads1[] = {
3662 // No credentials.
3663 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3664 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3665 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3666 };
3667
3668 // Since the first connection was closed, need to establish another once given
3669 // credentials.
3670 MockWrite data_writes2[] = {
3671 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173672 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333673 "Proxy-Connection: keep-alive\r\n"
3674 "Proxy-Authorization: auth_token\r\n\r\n"),
3675
3676 MockWrite("GET / HTTP/1.1\r\n"
3677 "Host: www.example.org\r\n"
3678 "Connection: keep-alive\r\n\r\n"),
3679 };
3680
3681 MockRead data_reads2[] = {
3682 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3683
3684 MockRead("HTTP/1.1 200 OK\r\n"),
3685 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3686 MockRead("Content-Length: 5\r\n\r\n"),
3687 MockRead(SYNCHRONOUS, "hello"),
3688 };
3689
3690 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3691 data_writes1, arraysize(data_writes1));
3692 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3693 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3694 data_writes2, arraysize(data_writes2));
3695 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3696 SSLSocketDataProvider ssl(ASYNC, OK);
3697 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3698
3699 scoped_ptr<HttpTransaction> trans(
3700 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3701
3702 TestCompletionCallback callback;
3703 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3704 EXPECT_EQ(OK, callback.GetResult(rv));
3705
3706 const HttpResponseInfo* response = trans->GetResponseInfo();
3707 ASSERT_TRUE(response);
3708 ASSERT_TRUE(response->headers);
3709 EXPECT_TRUE(response->headers->IsKeepAlive());
3710 EXPECT_EQ(407, response->headers->response_code());
3711 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3712 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3713 EXPECT_FALSE(response->auth_challenge);
3714
3715 LoadTimingInfo load_timing_info;
3716 // CONNECT requests and responses are handled at the connect job level, so
3717 // the transaction does not yet have a connection.
3718 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3719
3720 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3721 EXPECT_EQ(OK, callback.GetResult(rv));
3722
3723 response = trans->GetResponseInfo();
3724 ASSERT_TRUE(response);
3725 ASSERT_TRUE(response->headers);
3726 EXPECT_TRUE(response->headers->IsKeepAlive());
3727 EXPECT_EQ(200, response->headers->response_code());
3728 EXPECT_EQ(5, response->headers->GetContentLength());
3729 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3730
3731 // The password prompt info should not be set.
3732 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3733
3734 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3735 TestLoadTimingNotReusedWithPac(load_timing_info,
3736 CONNECT_TIMING_HAS_SSL_TIMES);
3737
3738 trans.reset();
3739 session->CloseAllConnections();
3740}
3741
3742// Test a proxy auth scheme that allows default credentials and a proxy server
3743// that hangs up when credentials are initially sent, and hangs up again when
3744// they are retried.
3745TEST_P(HttpNetworkTransactionTest,
3746 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
3747 HttpRequestInfo request;
3748 request.method = "GET";
3749 request.url = GURL("https://www.example.org/");
3750
3751 // Configure against proxy server "myproxy:70".
3752 session_deps_.proxy_service =
3753 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3754
3755 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3756 new HttpAuthHandlerMock::Factory());
3757 auth_handler_factory->set_do_init_from_challenge(true);
3758 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3759 mock_handler->set_allows_default_credentials(true);
3760 auth_handler_factory->AddMockHandler(mock_handler.release(),
3761 HttpAuth::AUTH_PROXY);
3762 session_deps_.http_auth_handler_factory = auth_handler_factory.Pass();
3763
3764 // Add NetLog just so can verify load timing information gets a NetLog ID.
3765 NetLog net_log;
3766 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423767 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333768
3769 // Should try to establish tunnel.
3770 MockWrite data_writes1[] = {
3771 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173772 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333773 "Proxy-Connection: keep-alive\r\n\r\n"),
3774
3775 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173776 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333777 "Proxy-Connection: keep-alive\r\n"
3778 "Proxy-Authorization: auth_token\r\n\r\n"),
3779 };
3780
3781 // The proxy responds to the connect with a 407, and then hangs up after the
3782 // second request is sent.
3783 MockRead data_reads1[] = {
3784 // No credentials.
3785 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3786 MockRead("Content-Length: 0\r\n"),
3787 MockRead("Proxy-Connection: keep-alive\r\n"),
3788 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3789 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3790 };
3791
3792 // HttpNetworkTransaction sees a reused connection that was closed with
3793 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
3794 // request.
3795 MockWrite data_writes2[] = {
3796 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173797 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333798 "Proxy-Connection: keep-alive\r\n\r\n"),
3799 };
3800
3801 // The proxy, having had more than enough of us, just hangs up.
3802 MockRead data_reads2[] = {
3803 // No credentials.
3804 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3805 };
3806
3807 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3808 data_writes1, arraysize(data_writes1));
3809 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3810 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3811 data_writes2, arraysize(data_writes2));
3812 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3813
3814 scoped_ptr<HttpTransaction> trans(
3815 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3816
3817 TestCompletionCallback callback;
3818 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3819 EXPECT_EQ(OK, callback.GetResult(rv));
3820
3821 const HttpResponseInfo* response = trans->GetResponseInfo();
3822 ASSERT_TRUE(response);
3823 ASSERT_TRUE(response->headers);
3824 EXPECT_TRUE(response->headers->IsKeepAlive());
3825 EXPECT_EQ(407, response->headers->response_code());
3826 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3827 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3828 EXPECT_FALSE(response->auth_challenge);
3829
3830 LoadTimingInfo load_timing_info;
3831 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3832
3833 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3834 EXPECT_EQ(ERR_EMPTY_RESPONSE, callback.GetResult(rv));
3835
3836 trans.reset();
3837 session->CloseAllConnections();
3838}
3839
3840// Test a proxy auth scheme that allows default credentials and a proxy server
3841// that hangs up when credentials are initially sent, and sends a challenge
3842// again they are retried.
3843TEST_P(HttpNetworkTransactionTest,
3844 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
3845 HttpRequestInfo request;
3846 request.method = "GET";
3847 request.url = GURL("https://www.example.org/");
3848
3849 // Configure against proxy server "myproxy:70".
3850 session_deps_.proxy_service =
3851 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3852
3853 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3854 new HttpAuthHandlerMock::Factory());
3855 auth_handler_factory->set_do_init_from_challenge(true);
3856 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3857 mock_handler->set_allows_default_credentials(true);
3858 auth_handler_factory->AddMockHandler(mock_handler.release(),
3859 HttpAuth::AUTH_PROXY);
3860 // Add another handler for the second challenge. It supports default
3861 // credentials, but they shouldn't be used, since they were already tried.
3862 mock_handler.reset(new HttpAuthHandlerMock());
3863 mock_handler->set_allows_default_credentials(true);
3864 auth_handler_factory->AddMockHandler(mock_handler.release(),
3865 HttpAuth::AUTH_PROXY);
3866 session_deps_.http_auth_handler_factory = auth_handler_factory.Pass();
3867
3868 // Add NetLog just so can verify load timing information gets a NetLog ID.
3869 NetLog net_log;
3870 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423871 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333872
3873 // Should try to establish tunnel.
3874 MockWrite data_writes1[] = {
3875 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173876 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333877 "Proxy-Connection: keep-alive\r\n\r\n"),
3878 };
3879
3880 // The proxy responds to the connect with a 407, using a non-persistent
3881 // connection.
3882 MockRead data_reads1[] = {
3883 // No credentials.
3884 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3885 MockRead("Proxy-Authenticate: Mock\r\n"),
3886 MockRead("Proxy-Connection: close\r\n\r\n"),
3887 };
3888
3889 // Since the first connection was closed, need to establish another once given
3890 // credentials.
3891 MockWrite data_writes2[] = {
3892 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173893 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333894 "Proxy-Connection: keep-alive\r\n"
3895 "Proxy-Authorization: auth_token\r\n\r\n"),
3896 };
3897
3898 MockRead data_reads2[] = {
3899 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3900 MockRead("Proxy-Authenticate: Mock\r\n"),
3901 MockRead("Proxy-Connection: close\r\n\r\n"),
3902 };
3903
3904 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3905 data_writes1, arraysize(data_writes1));
3906 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3907 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3908 data_writes2, arraysize(data_writes2));
3909 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3910 SSLSocketDataProvider ssl(ASYNC, OK);
3911 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3912
3913 scoped_ptr<HttpTransaction> trans(
3914 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3915
3916 TestCompletionCallback callback;
3917 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3918 EXPECT_EQ(OK, callback.GetResult(rv));
3919
3920 const HttpResponseInfo* response = trans->GetResponseInfo();
3921 ASSERT_TRUE(response);
3922 ASSERT_TRUE(response->headers);
3923 EXPECT_EQ(407, response->headers->response_code());
3924 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3925 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3926 EXPECT_FALSE(response->auth_challenge);
3927
3928 LoadTimingInfo load_timing_info;
3929 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3930
3931 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3932 EXPECT_EQ(OK, callback.GetResult(rv));
3933 response = trans->GetResponseInfo();
3934 ASSERT_TRUE(response);
3935 ASSERT_TRUE(response->headers);
3936 EXPECT_EQ(407, response->headers->response_code());
3937 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3938 EXPECT_TRUE(response->auth_challenge);
3939
3940 trans.reset();
3941 session->CloseAllConnections();
3942}
3943
[email protected]029c83b62013-01-24 05:28:203944// Test the load timing for HTTPS requests with an HTTP proxy.
[email protected]23e482282013-06-14 16:08:023945TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:203946 HttpRequestInfo request1;
3947 request1.method = "GET";
bncce36dca22015-04-21 22:11:233948 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:203949
3950 HttpRequestInfo request2;
3951 request2.method = "GET";
bncce36dca22015-04-21 22:11:233952 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:203953
3954 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033955 session_deps_.proxy_service = ProxyService::CreateFixed("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:513956 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073957 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423958 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:203959
3960 // Since we have proxy, should try to establish tunnel.
3961 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:173962 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3963 "Host: www.example.org:443\r\n"
3964 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203965
rsleevidb16bb02015-11-12 23:47:173966 MockWrite("GET /1 HTTP/1.1\r\n"
3967 "Host: www.example.org\r\n"
3968 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203969
rsleevidb16bb02015-11-12 23:47:173970 MockWrite("GET /2 HTTP/1.1\r\n"
3971 "Host: www.example.org\r\n"
3972 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203973 };
3974
3975 // The proxy responds to the connect with a 407, using a persistent
3976 // connection.
3977 MockRead data_reads1[] = {
3978 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3979
3980 MockRead("HTTP/1.1 200 OK\r\n"),
3981 MockRead("Content-Length: 1\r\n\r\n"),
3982 MockRead(SYNCHRONOUS, "1"),
3983
3984 MockRead("HTTP/1.1 200 OK\r\n"),
3985 MockRead("Content-Length: 2\r\n\r\n"),
3986 MockRead(SYNCHRONOUS, "22"),
3987 };
3988
3989 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3990 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073991 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:203992 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073993 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:203994
3995 TestCompletionCallback callback1;
[email protected]262eec82013-03-19 21:01:363996 scoped_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:503997 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:203998
3999 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
4000 EXPECT_EQ(ERR_IO_PENDING, rv);
4001
4002 rv = callback1.WaitForResult();
4003 EXPECT_EQ(OK, rv);
4004
4005 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
4006 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:504007 ASSERT_TRUE(response1->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204008 EXPECT_EQ(1, response1->headers->GetContentLength());
4009
4010 LoadTimingInfo load_timing_info1;
4011 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
4012 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
4013
4014 trans1.reset();
4015
4016 TestCompletionCallback callback2;
[email protected]262eec82013-03-19 21:01:364017 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504018 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204019
4020 rv = trans2->Start(&request2, callback2.callback(), log.bound());
4021 EXPECT_EQ(ERR_IO_PENDING, rv);
4022
4023 rv = callback2.WaitForResult();
4024 EXPECT_EQ(OK, rv);
4025
4026 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
4027 ASSERT_TRUE(response2 != NULL);
[email protected]90499482013-06-01 00:39:504028 ASSERT_TRUE(response2->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204029 EXPECT_EQ(2, response2->headers->GetContentLength());
4030
4031 LoadTimingInfo load_timing_info2;
4032 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4033 TestLoadTimingReused(load_timing_info2);
4034
4035 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
4036
4037 trans2.reset();
4038 session->CloseAllConnections();
4039}
4040
4041// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
[email protected]23e482282013-06-14 16:08:024042TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:204043 HttpRequestInfo request1;
4044 request1.method = "GET";
bncce36dca22015-04-21 22:11:234045 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:204046
4047 HttpRequestInfo request2;
4048 request2.method = "GET";
bncce36dca22015-04-21 22:11:234049 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:204050
4051 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034052 session_deps_.proxy_service =
4053 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:514054 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074055 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424056 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:204057
4058 // Since we have proxy, should try to establish tunnel.
4059 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174060 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4061 "Host: www.example.org:443\r\n"
4062 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204063
rsleevidb16bb02015-11-12 23:47:174064 MockWrite("GET /1 HTTP/1.1\r\n"
4065 "Host: www.example.org\r\n"
4066 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204067
rsleevidb16bb02015-11-12 23:47:174068 MockWrite("GET /2 HTTP/1.1\r\n"
4069 "Host: www.example.org\r\n"
4070 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204071 };
4072
4073 // The proxy responds to the connect with a 407, using a persistent
4074 // connection.
4075 MockRead data_reads1[] = {
4076 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4077
4078 MockRead("HTTP/1.1 200 OK\r\n"),
4079 MockRead("Content-Length: 1\r\n\r\n"),
4080 MockRead(SYNCHRONOUS, "1"),
4081
4082 MockRead("HTTP/1.1 200 OK\r\n"),
4083 MockRead("Content-Length: 2\r\n\r\n"),
4084 MockRead(SYNCHRONOUS, "22"),
4085 };
4086
4087 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4088 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074089 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:204090 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074091 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:204092
4093 TestCompletionCallback callback1;
[email protected]262eec82013-03-19 21:01:364094 scoped_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:504095 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204096
4097 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
4098 EXPECT_EQ(ERR_IO_PENDING, rv);
4099
4100 rv = callback1.WaitForResult();
4101 EXPECT_EQ(OK, rv);
4102
4103 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
4104 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:504105 ASSERT_TRUE(response1->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204106 EXPECT_EQ(1, response1->headers->GetContentLength());
4107
4108 LoadTimingInfo load_timing_info1;
4109 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
4110 TestLoadTimingNotReusedWithPac(load_timing_info1,
4111 CONNECT_TIMING_HAS_SSL_TIMES);
4112
4113 trans1.reset();
4114
4115 TestCompletionCallback callback2;
[email protected]262eec82013-03-19 21:01:364116 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504117 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204118
4119 rv = trans2->Start(&request2, callback2.callback(), log.bound());
4120 EXPECT_EQ(ERR_IO_PENDING, rv);
4121
4122 rv = callback2.WaitForResult();
4123 EXPECT_EQ(OK, rv);
4124
4125 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
4126 ASSERT_TRUE(response2 != NULL);
[email protected]90499482013-06-01 00:39:504127 ASSERT_TRUE(response2->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204128 EXPECT_EQ(2, response2->headers->GetContentLength());
4129
4130 LoadTimingInfo load_timing_info2;
4131 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4132 TestLoadTimingReusedWithPac(load_timing_info2);
4133
4134 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
4135
4136 trans2.reset();
4137 session->CloseAllConnections();
4138}
4139
[email protected]2df19bb2010-08-25 20:13:464140// Test a simple get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024141TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:274142 HttpRequestInfo request;
4143 request.method = "GET";
bncce36dca22015-04-21 22:11:234144 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274145
[email protected]2df19bb2010-08-25 20:13:464146 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034147 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514148 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074149 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424150 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:464151
[email protected]2df19bb2010-08-25 20:13:464152 // Since we have proxy, should use full url
4153 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234154 MockWrite(
4155 "GET http://www.example.org/ HTTP/1.1\r\n"
4156 "Host: www.example.org\r\n"
4157 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:464158 };
4159
4160 MockRead data_reads1[] = {
4161 MockRead("HTTP/1.1 200 OK\r\n"),
4162 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4163 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064164 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:464165 };
4166
4167 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4168 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074169 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064170 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074171 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:464172
[email protected]49639fa2011-12-20 23:22:414173 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:464174
[email protected]262eec82013-03-19 21:01:364175 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504176 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504177
[email protected]49639fa2011-12-20 23:22:414178 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:464179 EXPECT_EQ(ERR_IO_PENDING, rv);
4180
4181 rv = callback1.WaitForResult();
4182 EXPECT_EQ(OK, rv);
4183
[email protected]58e32bb2013-01-21 18:23:254184 LoadTimingInfo load_timing_info;
4185 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4186 TestLoadTimingNotReused(load_timing_info,
4187 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4188
[email protected]2df19bb2010-08-25 20:13:464189 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504190 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464191
4192 EXPECT_TRUE(response->headers->IsKeepAlive());
4193 EXPECT_EQ(200, response->headers->response_code());
4194 EXPECT_EQ(100, response->headers->GetContentLength());
4195 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4196
4197 // The password prompt info should not be set.
4198 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4199}
4200
[email protected]7642b5ae2010-09-01 20:55:174201// Test a SPDY get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024202TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:274203 HttpRequestInfo request;
4204 request.method = "GET";
bncce36dca22015-04-21 22:11:234205 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274206 request.load_flags = 0;
4207
[email protected]7642b5ae2010-09-01 20:55:174208 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034209 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514210 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074211 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424212 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:174213
bncce36dca22015-04-21 22:11:234214 // fetch http://www.example.org/ via SPDY
[email protected]cdf8f7e72013-05-23 10:56:464215 scoped_ptr<SpdyFrame> req(
4216 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rch8e6c6c42015-05-01 14:05:134217 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]7642b5ae2010-09-01 20:55:174218
[email protected]23e482282013-06-14 16:08:024219 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4220 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:174221 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134222 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:174223 };
4224
rch8e6c6c42015-05-01 14:05:134225 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4226 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074227 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:174228
[email protected]8ddf8322012-02-23 18:08:064229 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384230 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074231 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:174232
[email protected]49639fa2011-12-20 23:22:414233 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:174234
[email protected]262eec82013-03-19 21:01:364235 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504236 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504237
[email protected]49639fa2011-12-20 23:22:414238 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7642b5ae2010-09-01 20:55:174239 EXPECT_EQ(ERR_IO_PENDING, rv);
4240
4241 rv = callback1.WaitForResult();
4242 EXPECT_EQ(OK, rv);
4243
[email protected]58e32bb2013-01-21 18:23:254244 LoadTimingInfo load_timing_info;
4245 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4246 TestLoadTimingNotReused(load_timing_info,
4247 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4248
[email protected]7642b5ae2010-09-01 20:55:174249 const HttpResponseInfo* response = trans->GetResponseInfo();
4250 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504251 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024252 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:174253
4254 std::string response_data;
4255 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]448d4ca52012-03-04 04:12:234256 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:174257}
4258
[email protected]1c173852014-06-19 12:51:504259// Verifies that a session which races and wins against the owning transaction
4260// (completing prior to host resolution), doesn't fail the transaction.
4261// Regression test for crbug.com/334413.
4262TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
4263 HttpRequestInfo request;
4264 request.method = "GET";
bncce36dca22015-04-21 22:11:234265 request.url = GURL("http://www.example.org/");
[email protected]1c173852014-06-19 12:51:504266 request.load_flags = 0;
4267
4268 // Configure SPDY proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034269 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514270 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:504271 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424272 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:504273
bncce36dca22015-04-21 22:11:234274 // Fetch http://www.example.org/ through the SPDY proxy.
[email protected]1c173852014-06-19 12:51:504275 scoped_ptr<SpdyFrame> req(
4276 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rch8e6c6c42015-05-01 14:05:134277 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]1c173852014-06-19 12:51:504278
4279 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4280 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
4281 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134282 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:504283 };
4284
rch8e6c6c42015-05-01 14:05:134285 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4286 arraysize(spdy_writes));
[email protected]1c173852014-06-19 12:51:504287 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4288
4289 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384290 ssl.SetNextProto(GetProtocol());
[email protected]1c173852014-06-19 12:51:504291 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4292
4293 TestCompletionCallback callback1;
4294
4295 scoped_ptr<HttpTransaction> trans(
4296 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4297
4298 // Stall the hostname resolution begun by the transaction.
4299 session_deps_.host_resolver->set_synchronous_mode(false);
4300 session_deps_.host_resolver->set_ondemand_mode(true);
4301
4302 int rv = trans->Start(&request, callback1.callback(), log.bound());
4303 EXPECT_EQ(ERR_IO_PENDING, rv);
4304
4305 // Race a session to the proxy, which completes first.
4306 session_deps_.host_resolver->set_ondemand_mode(false);
4307 SpdySessionKey key(
4308 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
4309 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:424310 CreateSecureSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:504311
4312 // Unstall the resolution begun by the transaction.
4313 session_deps_.host_resolver->set_ondemand_mode(true);
4314 session_deps_.host_resolver->ResolveAllPending();
4315
4316 EXPECT_FALSE(callback1.have_result());
4317 rv = callback1.WaitForResult();
4318 EXPECT_EQ(OK, rv);
4319
4320 const HttpResponseInfo* response = trans->GetResponseInfo();
4321 ASSERT_TRUE(response != NULL);
4322 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024323 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:504324
4325 std::string response_data;
4326 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4327 EXPECT_EQ(kUploadData, response_data);
4328}
4329
[email protected]dc7bd1c52010-11-12 00:01:134330// Test a SPDY get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024331TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:274332 HttpRequestInfo request;
4333 request.method = "GET";
bncce36dca22015-04-21 22:11:234334 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274335 request.load_flags = 0;
4336
[email protected]79cb5c12011-09-12 13:12:044337 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034338 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:514339 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074340 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424341 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:134342
[email protected]dc7bd1c52010-11-12 00:01:134343 // The first request will be a bare GET, the second request will be a
4344 // GET with a Proxy-Authorization header.
[email protected]ff98d7f02012-03-22 21:44:194345 scoped_ptr<SpdyFrame> req_get(
[email protected]cdf8f7e72013-05-23 10:56:464346 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rdsmithebb50aa2015-11-12 03:44:384347 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:134348 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464349 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:134350 };
[email protected]ff98d7f02012-03-22 21:44:194351 scoped_ptr<SpdyFrame> req_get_authorization(
[email protected]cdf8f7e72013-05-23 10:56:464352 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4353 arraysize(kExtraAuthorizationHeaders) / 2,
4354 false,
4355 3,
4356 LOWEST,
4357 false));
[email protected]dc7bd1c52010-11-12 00:01:134358 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134359 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:134360 };
4361
4362 // The first response is a 407 proxy authentication challenge, and the second
4363 // response will be a 200 response since the second request includes a valid
4364 // Authorization header.
4365 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464366 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:134367 };
[email protected]ff98d7f02012-03-22 21:44:194368 scoped_ptr<SpdyFrame> resp_authentication(
[email protected]23e482282013-06-14 16:08:024369 spdy_util_.ConstructSpdySynReplyError(
[email protected]dc7bd1c52010-11-12 00:01:134370 "407 Proxy Authentication Required",
4371 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
4372 1));
[email protected]ff98d7f02012-03-22 21:44:194373 scoped_ptr<SpdyFrame> body_authentication(
[email protected]23e482282013-06-14 16:08:024374 spdy_util_.ConstructSpdyBodyFrame(1, true));
4375 scoped_ptr<SpdyFrame> resp_data(
4376 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4377 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:134378 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134379 CreateMockRead(*resp_authentication, 1),
4380 CreateMockRead(*body_authentication, 2),
4381 CreateMockRead(*resp_data, 4),
4382 CreateMockRead(*body_data, 5),
4383 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:134384 };
4385
rch8e6c6c42015-05-01 14:05:134386 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4387 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074388 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:134389
[email protected]8ddf8322012-02-23 18:08:064390 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384391 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074392 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:134393
[email protected]49639fa2011-12-20 23:22:414394 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:134395
[email protected]262eec82013-03-19 21:01:364396 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504397 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]dc7bd1c52010-11-12 00:01:134398
[email protected]49639fa2011-12-20 23:22:414399 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]dc7bd1c52010-11-12 00:01:134400 EXPECT_EQ(ERR_IO_PENDING, rv);
4401
4402 rv = callback1.WaitForResult();
4403 EXPECT_EQ(OK, rv);
4404
4405 const HttpResponseInfo* const response = trans->GetResponseInfo();
4406
4407 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504408 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]dc7bd1c52010-11-12 00:01:134409 EXPECT_EQ(407, response->headers->response_code());
4410 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:044411 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]dc7bd1c52010-11-12 00:01:134412
[email protected]49639fa2011-12-20 23:22:414413 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:134414
[email protected]49639fa2011-12-20 23:22:414415 rv = trans->RestartWithAuth(
4416 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]dc7bd1c52010-11-12 00:01:134417 EXPECT_EQ(ERR_IO_PENDING, rv);
4418
4419 rv = callback2.WaitForResult();
4420 EXPECT_EQ(OK, rv);
4421
4422 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4423
4424 ASSERT_TRUE(response_restart != NULL);
[email protected]90499482013-06-01 00:39:504425 ASSERT_TRUE(response_restart->headers.get() != NULL);
[email protected]dc7bd1c52010-11-12 00:01:134426 EXPECT_EQ(200, response_restart->headers->response_code());
4427 // The password prompt info should not be set.
4428 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4429}
4430
[email protected]d9da5fe2010-10-13 22:37:164431// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
[email protected]23e482282013-06-14 16:08:024432TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:274433 HttpRequestInfo request;
4434 request.method = "GET";
bncce36dca22015-04-21 22:11:234435 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274436 request.load_flags = 0;
4437
[email protected]d9da5fe2010-10-13 22:37:164438 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034439 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514440 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074441 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424442 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164443
[email protected]262eec82013-03-19 21:01:364444 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504445 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164446
bncce36dca22015-04-21 22:11:234447 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344448 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234449 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
4450 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:164451
bncce36dca22015-04-21 22:11:234452 const char get[] =
4453 "GET / HTTP/1.1\r\n"
4454 "Host: www.example.org\r\n"
4455 "Connection: keep-alive\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:194456 scoped_ptr<SpdyFrame> wrapped_get(
[email protected]23e482282013-06-14 16:08:024457 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
4458 scoped_ptr<SpdyFrame> conn_resp(
4459 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:164460 const char resp[] = "HTTP/1.1 200 OK\r\n"
4461 "Content-Length: 10\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:194462 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:024463 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
[email protected]ff98d7f02012-03-22 21:44:194464 scoped_ptr<SpdyFrame> wrapped_body(
[email protected]23e482282013-06-14 16:08:024465 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
[email protected]ff98d7f02012-03-22 21:44:194466 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204467 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
[email protected]8d2f7012012-02-16 00:08:044468
4469 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134470 CreateMockWrite(*connect, 0),
4471 CreateMockWrite(*wrapped_get, 2),
4472 CreateMockWrite(*window_update, 6),
[email protected]8d2f7012012-02-16 00:08:044473 };
4474
[email protected]d9da5fe2010-10-13 22:37:164475 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134476 CreateMockRead(*conn_resp, 1, ASYNC),
4477 CreateMockRead(*wrapped_get_resp, 3, ASYNC),
4478 CreateMockRead(*wrapped_body, 4, ASYNC),
4479 CreateMockRead(*wrapped_body, 5, ASYNC),
4480 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:164481 };
4482
rch8e6c6c42015-05-01 14:05:134483 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4484 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074485 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164486
[email protected]8ddf8322012-02-23 18:08:064487 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384488 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074489 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064490 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074491 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164492
[email protected]49639fa2011-12-20 23:22:414493 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164494
[email protected]49639fa2011-12-20 23:22:414495 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164496 EXPECT_EQ(ERR_IO_PENDING, rv);
4497
4498 rv = callback1.WaitForResult();
rch8e6c6c42015-05-01 14:05:134499 ASSERT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:164500
[email protected]58e32bb2013-01-21 18:23:254501 LoadTimingInfo load_timing_info;
4502 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4503 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4504
[email protected]d9da5fe2010-10-13 22:37:164505 const HttpResponseInfo* response = trans->GetResponseInfo();
4506 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504507 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]d9da5fe2010-10-13 22:37:164508 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4509
4510 std::string response_data;
4511 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4512 EXPECT_EQ("1234567890", response_data);
4513}
4514
4515// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
[email protected]23e482282013-06-14 16:08:024516TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
rdsmithebb50aa2015-11-12 03:44:384517 SpdyTestUtil spdy_util_wrapped(GetProtocol(), GetDependenciesFromPriority());
4518
[email protected]cb9bf6ca2011-01-28 13:15:274519 HttpRequestInfo request;
4520 request.method = "GET";
bncce36dca22015-04-21 22:11:234521 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274522 request.load_flags = 0;
4523
[email protected]d9da5fe2010-10-13 22:37:164524 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034525 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514526 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074527 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424528 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164529
[email protected]262eec82013-03-19 21:01:364530 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504531 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164532
bncce36dca22015-04-21 22:11:234533 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344534 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234535 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
4536 // fetch https://www.example.org/ via SPDY
4537 const char kMyUrl[] = "https://www.example.org/";
[email protected]cdf8f7e72013-05-23 10:56:464538 scoped_ptr<SpdyFrame> get(
rdsmithebb50aa2015-11-12 03:44:384539 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
[email protected]23e482282013-06-14 16:08:024540 scoped_ptr<SpdyFrame> wrapped_get(
4541 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
4542 scoped_ptr<SpdyFrame> conn_resp(
4543 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4544 scoped_ptr<SpdyFrame> get_resp(
rdsmithebb50aa2015-11-12 03:44:384545 spdy_util_wrapped.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:194546 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:024547 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
rdsmithebb50aa2015-11-12 03:44:384548 scoped_ptr<SpdyFrame> body(spdy_util_wrapped.ConstructSpdyBodyFrame(1, true));
[email protected]23e482282013-06-14 16:08:024549 scoped_ptr<SpdyFrame> wrapped_body(
4550 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
[email protected]ff98d7f02012-03-22 21:44:194551 scoped_ptr<SpdyFrame> window_update_get_resp(
[email protected]c10b20852013-05-15 21:29:204552 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
[email protected]ff98d7f02012-03-22 21:44:194553 scoped_ptr<SpdyFrame> window_update_body(
[email protected]c10b20852013-05-15 21:29:204554 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
[email protected]8d2f7012012-02-16 00:08:044555
4556 MockWrite spdy_writes[] = {
rch32320842015-05-16 15:57:094557 CreateMockWrite(*connect, 0),
4558 CreateMockWrite(*wrapped_get, 2),
4559 CreateMockWrite(*window_update_get_resp, 6),
[email protected]8d2f7012012-02-16 00:08:044560 CreateMockWrite(*window_update_body, 7),
4561 };
4562
[email protected]d9da5fe2010-10-13 22:37:164563 MockRead spdy_reads[] = {
rch32320842015-05-16 15:57:094564 CreateMockRead(*conn_resp, 1, ASYNC),
4565 MockRead(ASYNC, ERR_IO_PENDING, 3),
rch8e6c6c42015-05-01 14:05:134566 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
rch32320842015-05-16 15:57:094567 CreateMockRead(*wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:134568 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:164569 };
4570
rch32320842015-05-16 15:57:094571 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4572 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074573 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164574
[email protected]8ddf8322012-02-23 18:08:064575 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384576 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074577 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064578 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384579 ssl2.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074580 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164581
[email protected]49639fa2011-12-20 23:22:414582 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164583
[email protected]49639fa2011-12-20 23:22:414584 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164585 EXPECT_EQ(ERR_IO_PENDING, rv);
4586
rch32320842015-05-16 15:57:094587 // Allow the SpdyProxyClientSocket's write callback to complete.
4588 base::MessageLoop::current()->RunUntilIdle();
4589 // Now allow the read of the response to complete.
4590 spdy_data.CompleteRead();
[email protected]d9da5fe2010-10-13 22:37:164591 rv = callback1.WaitForResult();
4592 EXPECT_EQ(OK, rv);
4593
[email protected]58e32bb2013-01-21 18:23:254594 LoadTimingInfo load_timing_info;
4595 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4596 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4597
[email protected]d9da5fe2010-10-13 22:37:164598 const HttpResponseInfo* response = trans->GetResponseInfo();
4599 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504600 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024601 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:164602
4603 std::string response_data;
4604 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]448d4ca52012-03-04 04:12:234605 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:164606}
4607
4608// Test a SPDY CONNECT failure through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024609TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:274610 HttpRequestInfo request;
4611 request.method = "GET";
bncce36dca22015-04-21 22:11:234612 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274613 request.load_flags = 0;
4614
[email protected]d9da5fe2010-10-13 22:37:164615 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034616 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514617 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074618 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424619 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164620
[email protected]262eec82013-03-19 21:01:364621 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504622 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164623
bncce36dca22015-04-21 22:11:234624 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344625 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234626 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:204627 scoped_ptr<SpdyFrame> get(
4628 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:164629
4630 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134631 CreateMockWrite(*connect, 0), CreateMockWrite(*get, 2),
[email protected]d9da5fe2010-10-13 22:37:164632 };
4633
[email protected]23e482282013-06-14 16:08:024634 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
4635 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:164636 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134637 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:164638 };
4639
rch8e6c6c42015-05-01 14:05:134640 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4641 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074642 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164643
[email protected]8ddf8322012-02-23 18:08:064644 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384645 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074646 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064647 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384648 ssl2.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074649 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164650
[email protected]49639fa2011-12-20 23:22:414651 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164652
[email protected]49639fa2011-12-20 23:22:414653 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164654 EXPECT_EQ(ERR_IO_PENDING, rv);
4655
4656 rv = callback1.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:174657 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]d9da5fe2010-10-13 22:37:164658
[email protected]4eddbc732012-08-09 05:40:174659 // TODO(ttuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:164660}
4661
[email protected]f6c63db52013-02-02 00:35:224662// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4663// HTTPS Proxy to different servers.
[email protected]23e482282013-06-14 16:08:024664TEST_P(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:224665 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
4666 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034667 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514668 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074669 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424670 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504671 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224672
4673 HttpRequestInfo request1;
4674 request1.method = "GET";
bncce36dca22015-04-21 22:11:234675 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224676 request1.load_flags = 0;
4677
4678 HttpRequestInfo request2;
4679 request2.method = "GET";
bncce36dca22015-04-21 22:11:234680 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:224681 request2.load_flags = 0;
4682
bncce36dca22015-04-21 22:11:234683 // CONNECT to www.example.org:443 via SPDY.
lgarrona91df87f2014-12-05 00:51:344684 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234685 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]23e482282013-06-14 16:08:024686 scoped_ptr<SpdyFrame> conn_resp1(
4687 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f6c63db52013-02-02 00:35:224688
bncce36dca22015-04-21 22:11:234689 // Fetch https://www.example.org/ via HTTP.
4690 const char get1[] =
4691 "GET / HTTP/1.1\r\n"
4692 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224693 "Connection: keep-alive\r\n\r\n";
4694 scoped_ptr<SpdyFrame> wrapped_get1(
[email protected]23e482282013-06-14 16:08:024695 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
[email protected]f6c63db52013-02-02 00:35:224696 const char resp1[] = "HTTP/1.1 200 OK\r\n"
4697 "Content-Length: 1\r\n\r\n";
4698 scoped_ptr<SpdyFrame> wrapped_get_resp1(
[email protected]23e482282013-06-14 16:08:024699 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
4700 scoped_ptr<SpdyFrame> wrapped_body1(
4701 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
[email protected]f6c63db52013-02-02 00:35:224702 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204703 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
[email protected]f6c63db52013-02-02 00:35:224704
bncce36dca22015-04-21 22:11:234705 // CONNECT to mail.example.org:443 via SPDY.
[email protected]745aa9c2014-06-27 02:21:294706 SpdyHeaderBlock connect2_block;
bnc7ecc1122015-09-28 13:22:494707 spdy_util_.MaybeAddVersionHeader(&connect2_block);
[email protected]745aa9c2014-06-27 02:21:294708 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
rdsmithebb50aa2015-11-12 03:44:384709 if (GetProtocol() == kProtoHTTP2) {
bnc6b996d532015-07-29 10:51:324710 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org:443";
4711 } else {
bnc6b996d532015-07-29 10:51:324712 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org";
bnc7ecc1122015-09-28 13:22:494713 connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443";
bnc6b996d532015-07-29 10:51:324714 }
[email protected]f6c63db52013-02-02 00:35:224715 scoped_ptr<SpdyFrame> connect2(
[email protected]745aa9c2014-06-27 02:21:294716 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
[email protected]601e03f12014-04-06 16:26:394717
[email protected]23e482282013-06-14 16:08:024718 scoped_ptr<SpdyFrame> conn_resp2(
4719 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]f6c63db52013-02-02 00:35:224720
bncce36dca22015-04-21 22:11:234721 // Fetch https://mail.example.org/ via HTTP.
4722 const char get2[] =
4723 "GET / HTTP/1.1\r\n"
4724 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224725 "Connection: keep-alive\r\n\r\n";
4726 scoped_ptr<SpdyFrame> wrapped_get2(
[email protected]23e482282013-06-14 16:08:024727 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
[email protected]f6c63db52013-02-02 00:35:224728 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4729 "Content-Length: 2\r\n\r\n";
4730 scoped_ptr<SpdyFrame> wrapped_get_resp2(
[email protected]23e482282013-06-14 16:08:024731 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
[email protected]f6c63db52013-02-02 00:35:224732 scoped_ptr<SpdyFrame> wrapped_body2(
[email protected]23e482282013-06-14 16:08:024733 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
[email protected]f6c63db52013-02-02 00:35:224734
4735 MockWrite spdy_writes[] = {
4736 CreateMockWrite(*connect1, 0),
4737 CreateMockWrite(*wrapped_get1, 2),
4738 CreateMockWrite(*connect2, 5),
4739 CreateMockWrite(*wrapped_get2, 7),
4740 };
4741
4742 MockRead spdy_reads[] = {
4743 CreateMockRead(*conn_resp1, 1, ASYNC),
4744 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4745 CreateMockRead(*wrapped_body1, 4, ASYNC),
4746 CreateMockRead(*conn_resp2, 6, ASYNC),
4747 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
4748 CreateMockRead(*wrapped_body2, 9, ASYNC),
4749 MockRead(ASYNC, 0, 10),
4750 };
4751
mmenke11eb5152015-06-09 14:50:504752 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4753 arraysize(spdy_writes));
4754 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224755
4756 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384757 ssl.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:504758 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224759 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504760 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:224761 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504762 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:224763
4764 TestCompletionCallback callback;
4765
[email protected]262eec82013-03-19 21:01:364766 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504767 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224768 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504769 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224770
4771 LoadTimingInfo load_timing_info;
4772 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4773 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4774
4775 const HttpResponseInfo* response = trans->GetResponseInfo();
4776 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504777 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]f6c63db52013-02-02 00:35:224778 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4779
4780 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:294781 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
mmenke11eb5152015-06-09 14:50:504782 rv = trans->Read(buf.get(), 256, callback.callback());
4783 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224784
[email protected]262eec82013-03-19 21:01:364785 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504786 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224787 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504788 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224789
4790 LoadTimingInfo load_timing_info2;
4791 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4792 // Even though the SPDY connection is reused, a new tunnelled connection has
4793 // to be created, so the socket's load timing looks like a fresh connection.
4794 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
4795
4796 // The requests should have different IDs, since they each are using their own
4797 // separate stream.
4798 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4799
mmenke11eb5152015-06-09 14:50:504800 rv = trans2->Read(buf.get(), 256, callback.callback());
4801 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224802}
4803
4804// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4805// HTTPS Proxy to the same server.
[email protected]23e482282013-06-14 16:08:024806TEST_P(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:224807 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
4808 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034809 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514810 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074811 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424812 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504813 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224814
4815 HttpRequestInfo request1;
4816 request1.method = "GET";
bncce36dca22015-04-21 22:11:234817 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224818 request1.load_flags = 0;
4819
4820 HttpRequestInfo request2;
4821 request2.method = "GET";
bncce36dca22015-04-21 22:11:234822 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:224823 request2.load_flags = 0;
4824
bncce36dca22015-04-21 22:11:234825 // CONNECT to www.example.org:443 via SPDY.
lgarrona91df87f2014-12-05 00:51:344826 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234827 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]23e482282013-06-14 16:08:024828 scoped_ptr<SpdyFrame> conn_resp1(
4829 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f6c63db52013-02-02 00:35:224830
bncce36dca22015-04-21 22:11:234831 // Fetch https://www.example.org/ via HTTP.
4832 const char get1[] =
4833 "GET / HTTP/1.1\r\n"
4834 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224835 "Connection: keep-alive\r\n\r\n";
4836 scoped_ptr<SpdyFrame> wrapped_get1(
[email protected]23e482282013-06-14 16:08:024837 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
[email protected]f6c63db52013-02-02 00:35:224838 const char resp1[] = "HTTP/1.1 200 OK\r\n"
4839 "Content-Length: 1\r\n\r\n";
4840 scoped_ptr<SpdyFrame> wrapped_get_resp1(
[email protected]23e482282013-06-14 16:08:024841 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
4842 scoped_ptr<SpdyFrame> wrapped_body1(
4843 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
[email protected]f6c63db52013-02-02 00:35:224844 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204845 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
[email protected]f6c63db52013-02-02 00:35:224846
bncce36dca22015-04-21 22:11:234847 // Fetch https://www.example.org/2 via HTTP.
4848 const char get2[] =
4849 "GET /2 HTTP/1.1\r\n"
4850 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224851 "Connection: keep-alive\r\n\r\n";
4852 scoped_ptr<SpdyFrame> wrapped_get2(
[email protected]23e482282013-06-14 16:08:024853 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
[email protected]f6c63db52013-02-02 00:35:224854 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4855 "Content-Length: 2\r\n\r\n";
4856 scoped_ptr<SpdyFrame> wrapped_get_resp2(
[email protected]23e482282013-06-14 16:08:024857 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
[email protected]f6c63db52013-02-02 00:35:224858 scoped_ptr<SpdyFrame> wrapped_body2(
[email protected]23e482282013-06-14 16:08:024859 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
[email protected]f6c63db52013-02-02 00:35:224860
4861 MockWrite spdy_writes[] = {
4862 CreateMockWrite(*connect1, 0),
4863 CreateMockWrite(*wrapped_get1, 2),
4864 CreateMockWrite(*wrapped_get2, 5),
4865 };
4866
4867 MockRead spdy_reads[] = {
4868 CreateMockRead(*conn_resp1, 1, ASYNC),
4869 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4870 CreateMockRead(*wrapped_body1, 4, ASYNC),
4871 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
4872 CreateMockRead(*wrapped_body2, 7, ASYNC),
4873 MockRead(ASYNC, 0, 8),
4874 };
4875
mmenke11eb5152015-06-09 14:50:504876 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4877 arraysize(spdy_writes));
4878 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224879
4880 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384881 ssl.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:504882 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224883 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504884 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:224885
4886 TestCompletionCallback callback;
4887
[email protected]262eec82013-03-19 21:01:364888 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504889 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224890 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4891 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f6c63db52013-02-02 00:35:224892
4893 rv = callback.WaitForResult();
4894 EXPECT_EQ(OK, rv);
4895
4896 LoadTimingInfo load_timing_info;
4897 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4898 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4899
4900 const HttpResponseInfo* response = trans->GetResponseInfo();
4901 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504902 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]f6c63db52013-02-02 00:35:224903 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4904
4905 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:294906 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
[email protected]90499482013-06-01 00:39:504907 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:224908 trans.reset();
4909
[email protected]262eec82013-03-19 21:01:364910 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504911 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224912 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4913 EXPECT_EQ(ERR_IO_PENDING, rv);
4914
[email protected]f6c63db52013-02-02 00:35:224915 rv = callback.WaitForResult();
4916 EXPECT_EQ(OK, rv);
4917
4918 LoadTimingInfo load_timing_info2;
4919 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4920 TestLoadTimingReused(load_timing_info2);
4921
4922 // The requests should have the same ID.
4923 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4924
[email protected]90499482013-06-01 00:39:504925 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:224926}
4927
4928// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4929// Proxy to different servers.
mmenke11eb5152015-06-09 14:50:504930TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:224931 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034932 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514933 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074934 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424935 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504936 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224937
4938 HttpRequestInfo request1;
4939 request1.method = "GET";
bncce36dca22015-04-21 22:11:234940 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224941 request1.load_flags = 0;
4942
4943 HttpRequestInfo request2;
4944 request2.method = "GET";
bncce36dca22015-04-21 22:11:234945 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:224946 request2.load_flags = 0;
4947
bncce36dca22015-04-21 22:11:234948 // http://www.example.org/
[email protected]23e482282013-06-14 16:08:024949 scoped_ptr<SpdyHeaderBlock> headers(
bncce36dca22015-04-21 22:11:234950 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
[email protected]745aa9c2014-06-27 02:21:294951 scoped_ptr<SpdyFrame> get1(
4952 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]23e482282013-06-14 16:08:024953 scoped_ptr<SpdyFrame> get_resp1(
4954 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4955 scoped_ptr<SpdyFrame> body1(
4956 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
rdsmithebb50aa2015-11-12 03:44:384957 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:224958
bncce36dca22015-04-21 22:11:234959 // http://mail.example.org/
[email protected]23e482282013-06-14 16:08:024960 scoped_ptr<SpdyHeaderBlock> headers2(
bncce36dca22015-04-21 22:11:234961 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
[email protected]745aa9c2014-06-27 02:21:294962 scoped_ptr<SpdyFrame> get2(
4963 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
[email protected]23e482282013-06-14 16:08:024964 scoped_ptr<SpdyFrame> get_resp2(
4965 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4966 scoped_ptr<SpdyFrame> body2(
4967 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
[email protected]f6c63db52013-02-02 00:35:224968
4969 MockWrite spdy_writes[] = {
4970 CreateMockWrite(*get1, 0),
4971 CreateMockWrite(*get2, 3),
4972 };
4973
4974 MockRead spdy_reads[] = {
4975 CreateMockRead(*get_resp1, 1, ASYNC),
4976 CreateMockRead(*body1, 2, ASYNC),
4977 CreateMockRead(*get_resp2, 4, ASYNC),
4978 CreateMockRead(*body2, 5, ASYNC),
4979 MockRead(ASYNC, 0, 6),
4980 };
4981
mmenke11eb5152015-06-09 14:50:504982 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4983 arraysize(spdy_writes));
4984 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224985
4986 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384987 ssl.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:504988 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224989
4990 TestCompletionCallback callback;
4991
[email protected]262eec82013-03-19 21:01:364992 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504993 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224994 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504995 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224996
4997 LoadTimingInfo load_timing_info;
4998 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4999 TestLoadTimingNotReused(load_timing_info,
5000 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5001
5002 const HttpResponseInfo* response = trans->GetResponseInfo();
5003 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:505004 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025005 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:225006
5007 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:295008 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
mmenke11eb5152015-06-09 14:50:505009 rv = trans->Read(buf.get(), 256, callback.callback());
5010 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:225011 // Delete the first request, so the second one can reuse the socket.
5012 trans.reset();
5013
[email protected]262eec82013-03-19 21:01:365014 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:505015 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:225016 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:505017 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:225018
5019 LoadTimingInfo load_timing_info2;
5020 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5021 TestLoadTimingReused(load_timing_info2);
5022
5023 // The requests should have the same ID.
5024 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
5025
mmenke11eb5152015-06-09 14:50:505026 rv = trans2->Read(buf.get(), 256, callback.callback());
5027 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:225028}
5029
[email protected]2df19bb2010-08-25 20:13:465030// Test the challenge-response-retry sequence through an HTTPS Proxy
[email protected]23e482282013-06-14 16:08:025031TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:465032 HttpRequestInfo request;
5033 request.method = "GET";
bncce36dca22015-04-21 22:11:235034 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:465035 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:295036 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2df19bb2010-08-25 20:13:465037
[email protected]79cb5c12011-09-12 13:12:045038 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035039 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:515040 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075041 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:425042 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275043
[email protected]2df19bb2010-08-25 20:13:465044 // Since we have proxy, should use full url
5045 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235046 MockWrite(
5047 "GET http://www.example.org/ HTTP/1.1\r\n"
5048 "Host: www.example.org\r\n"
5049 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465050
bncce36dca22015-04-21 22:11:235051 // After calling trans->RestartWithAuth(), this is the request we should
5052 // be issuing -- the final header line contains the credentials.
5053 MockWrite(
5054 "GET http://www.example.org/ HTTP/1.1\r\n"
5055 "Host: www.example.org\r\n"
5056 "Proxy-Connection: keep-alive\r\n"
5057 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465058 };
5059
5060 // The proxy responds to the GET with a 407, using a persistent
5061 // connection.
5062 MockRead data_reads1[] = {
5063 // No credentials.
5064 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5065 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5066 MockRead("Proxy-Connection: keep-alive\r\n"),
5067 MockRead("Content-Length: 0\r\n\r\n"),
5068
5069 MockRead("HTTP/1.1 200 OK\r\n"),
5070 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5071 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065072 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:465073 };
5074
5075 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5076 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:075077 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:065078 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075079 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:465080
[email protected]49639fa2011-12-20 23:22:415081 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:465082
[email protected]262eec82013-03-19 21:01:365083 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505084 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505085
[email protected]49639fa2011-12-20 23:22:415086 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:465087 EXPECT_EQ(ERR_IO_PENDING, rv);
5088
5089 rv = callback1.WaitForResult();
5090 EXPECT_EQ(OK, rv);
5091
[email protected]58e32bb2013-01-21 18:23:255092 LoadTimingInfo load_timing_info;
5093 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5094 TestLoadTimingNotReused(load_timing_info,
5095 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5096
[email protected]2df19bb2010-08-25 20:13:465097 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505098 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:505099 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]2df19bb2010-08-25 20:13:465100 EXPECT_EQ(407, response->headers->response_code());
5101 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:045102 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2df19bb2010-08-25 20:13:465103
[email protected]49639fa2011-12-20 23:22:415104 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:465105
[email protected]49639fa2011-12-20 23:22:415106 rv = trans->RestartWithAuth(
5107 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]2df19bb2010-08-25 20:13:465108 EXPECT_EQ(ERR_IO_PENDING, rv);
5109
5110 rv = callback2.WaitForResult();
5111 EXPECT_EQ(OK, rv);
5112
[email protected]58e32bb2013-01-21 18:23:255113 load_timing_info = LoadTimingInfo();
5114 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5115 // Retrying with HTTP AUTH is considered to be reusing a socket.
5116 TestLoadTimingReused(load_timing_info);
5117
[email protected]2df19bb2010-08-25 20:13:465118 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505119 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:465120
5121 EXPECT_TRUE(response->headers->IsKeepAlive());
5122 EXPECT_EQ(200, response->headers->response_code());
5123 EXPECT_EQ(100, response->headers->GetContentLength());
5124 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5125
5126 // The password prompt info should not be set.
5127 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5128}
5129
[email protected]23e482282013-06-14 16:08:025130void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:085131 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:425132 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:085133 request.method = "GET";
bncce36dca22015-04-21 22:11:235134 request.url = GURL("https://www.example.org/");
[email protected]c744cf22009-02-27 07:28:085135 request.load_flags = 0;
5136
[email protected]cb9bf6ca2011-01-28 13:15:275137 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035138 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:425139 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275140
[email protected]c744cf22009-02-27 07:28:085141 // Since we have proxy, should try to establish tunnel.
5142 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:175143 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5144 "Host: www.example.org:443\r\n"
5145 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:085146 };
5147
5148 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:235149 status, MockRead("Content-Length: 10\r\n\r\n"),
5150 // No response body because the test stops reading here.
5151 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:085152 };
5153
[email protected]31a2bfe2010-02-09 08:03:395154 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5155 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:075156 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:085157
[email protected]49639fa2011-12-20 23:22:415158 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:085159
[email protected]262eec82013-03-19 21:01:365160 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505161 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505162
[email protected]49639fa2011-12-20 23:22:415163 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425164 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:085165
5166 rv = callback.WaitForResult();
5167 EXPECT_EQ(expected_status, rv);
5168}
5169
[email protected]23e482282013-06-14 16:08:025170void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:235171 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:085172 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:425173 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:085174}
5175
[email protected]23e482282013-06-14 16:08:025176TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:085177 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
5178}
5179
[email protected]23e482282013-06-14 16:08:025180TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:085181 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
5182}
5183
[email protected]23e482282013-06-14 16:08:025184TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:085185 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
5186}
5187
[email protected]23e482282013-06-14 16:08:025188TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:085189 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
5190}
5191
[email protected]23e482282013-06-14 16:08:025192TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:085193 ConnectStatusHelper(
5194 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
5195}
5196
[email protected]23e482282013-06-14 16:08:025197TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:085198 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
5199}
5200
[email protected]23e482282013-06-14 16:08:025201TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:085202 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
5203}
5204
[email protected]23e482282013-06-14 16:08:025205TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:085206 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
5207}
5208
[email protected]23e482282013-06-14 16:08:025209TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:085210 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
5211}
5212
[email protected]23e482282013-06-14 16:08:025213TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:085214 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
5215}
5216
[email protected]23e482282013-06-14 16:08:025217TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:085218 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
5219}
5220
[email protected]23e482282013-06-14 16:08:025221TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:085222 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
5223}
5224
[email protected]23e482282013-06-14 16:08:025225TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:085226 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
5227}
5228
[email protected]23e482282013-06-14 16:08:025229TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:085230 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
5231}
5232
[email protected]23e482282013-06-14 16:08:025233TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:085234 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
5235}
5236
[email protected]23e482282013-06-14 16:08:025237TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:085238 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
5239}
5240
[email protected]0a17aab32014-04-24 03:32:375241TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
5242 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
5243}
5244
[email protected]23e482282013-06-14 16:08:025245TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:085246 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
5247}
5248
[email protected]23e482282013-06-14 16:08:025249TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:085250 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
5251}
5252
[email protected]23e482282013-06-14 16:08:025253TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:085254 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
5255}
5256
[email protected]23e482282013-06-14 16:08:025257TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:085258 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
5259}
5260
[email protected]23e482282013-06-14 16:08:025261TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:085262 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
5263}
5264
[email protected]23e482282013-06-14 16:08:025265TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:085266 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
5267}
5268
[email protected]23e482282013-06-14 16:08:025269TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:085270 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
5271}
5272
[email protected]23e482282013-06-14 16:08:025273TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:085274 ConnectStatusHelperWithExpectedStatus(
5275 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:545276 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:085277}
5278
[email protected]23e482282013-06-14 16:08:025279TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:085280 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
5281}
5282
[email protected]23e482282013-06-14 16:08:025283TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:085284 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
5285}
5286
[email protected]23e482282013-06-14 16:08:025287TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:085288 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
5289}
5290
[email protected]23e482282013-06-14 16:08:025291TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:085292 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
5293}
5294
[email protected]23e482282013-06-14 16:08:025295TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:085296 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
5297}
5298
[email protected]23e482282013-06-14 16:08:025299TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:085300 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
5301}
5302
[email protected]23e482282013-06-14 16:08:025303TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:085304 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
5305}
5306
[email protected]23e482282013-06-14 16:08:025307TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:085308 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
5309}
5310
[email protected]23e482282013-06-14 16:08:025311TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:085312 ConnectStatusHelper(
5313 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
5314}
5315
[email protected]23e482282013-06-14 16:08:025316TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:085317 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
5318}
5319
[email protected]23e482282013-06-14 16:08:025320TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:085321 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
5322}
5323
[email protected]23e482282013-06-14 16:08:025324TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:085325 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
5326}
5327
[email protected]23e482282013-06-14 16:08:025328TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:085329 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
5330}
5331
[email protected]23e482282013-06-14 16:08:025332TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:085333 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
5334}
5335
[email protected]23e482282013-06-14 16:08:025336TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:085337 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
5338}
5339
[email protected]23e482282013-06-14 16:08:025340TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:085341 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
5342}
5343
[email protected]038e9a32008-10-08 22:40:165344// Test the flow when both the proxy server AND origin server require
5345// authentication. Again, this uses basic auth for both since that is
5346// the simplest to mock.
[email protected]23e482282013-06-14 16:08:025347TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:275348 HttpRequestInfo request;
5349 request.method = "GET";
bncce36dca22015-04-21 22:11:235350 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:275351 request.load_flags = 0;
5352
[email protected]038e9a32008-10-08 22:40:165353 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035354 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:425355 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:075356
5357 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:415358 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]038e9a32008-10-08 22:40:165359
[email protected]f9ee6b52008-11-08 06:46:235360 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235361 MockWrite(
5362 "GET http://www.example.org/ HTTP/1.1\r\n"
5363 "Host: www.example.org\r\n"
5364 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:235365 };
5366
[email protected]038e9a32008-10-08 22:40:165367 MockRead data_reads1[] = {
5368 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
5369 // Give a couple authenticate options (only the middle one is actually
5370 // supported).
[email protected]22927ad2009-09-21 19:56:195371 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:165372 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5373 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
5374 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5375 // Large content-length -- won't matter, as connection will be reset.
5376 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065377 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:165378 };
5379
5380 // After calling trans->RestartWithAuth() the first time, this is the
5381 // request we should be issuing -- the final header line contains the
5382 // proxy's credentials.
5383 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:235384 MockWrite(
5385 "GET http://www.example.org/ HTTP/1.1\r\n"
5386 "Host: www.example.org\r\n"
5387 "Proxy-Connection: keep-alive\r\n"
5388 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:165389 };
5390
5391 // Now the proxy server lets the request pass through to origin server.
5392 // The origin server responds with a 401.
5393 MockRead data_reads2[] = {
5394 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5395 // Note: We are using the same realm-name as the proxy server. This is
5396 // completely valid, as realms are unique across hosts.
5397 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5398 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5399 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065400 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:165401 };
5402
5403 // After calling trans->RestartWithAuth() the second time, we should send
5404 // the credentials for both the proxy and origin server.
5405 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:235406 MockWrite(
5407 "GET http://www.example.org/ HTTP/1.1\r\n"
5408 "Host: www.example.org\r\n"
5409 "Proxy-Connection: keep-alive\r\n"
5410 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
5411 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:165412 };
5413
5414 // Lastly we get the desired content.
5415 MockRead data_reads3[] = {
5416 MockRead("HTTP/1.0 200 OK\r\n"),
5417 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5418 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065419 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:165420 };
5421
[email protected]31a2bfe2010-02-09 08:03:395422 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5423 data_writes1, arraysize(data_writes1));
5424 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5425 data_writes2, arraysize(data_writes2));
5426 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5427 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:075428 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5429 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5430 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:165431
[email protected]49639fa2011-12-20 23:22:415432 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:165433
[email protected]49639fa2011-12-20 23:22:415434 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425435 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165436
5437 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425438 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165439
[email protected]1c773ea12009-04-28 19:58:425440 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505441 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045442 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:165443
[email protected]49639fa2011-12-20 23:22:415444 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:165445
[email protected]49639fa2011-12-20 23:22:415446 rv = trans->RestartWithAuth(
5447 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:425448 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165449
5450 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425451 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165452
5453 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505454 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045455 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:165456
[email protected]49639fa2011-12-20 23:22:415457 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:165458
[email protected]49639fa2011-12-20 23:22:415459 rv = trans->RestartWithAuth(
5460 AuthCredentials(kFoo2, kBar2), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425461 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165462
5463 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425464 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165465
5466 response = trans->GetResponseInfo();
5467 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5468 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:165469}
[email protected]4ddaf2502008-10-23 18:26:195470
[email protected]ea9dc9a2009-09-05 00:43:325471// For the NTLM implementation using SSPI, we skip the NTLM tests since we
5472// can't hook into its internals to cause it to generate predictable NTLM
5473// authorization headers.
5474#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:295475// The NTLM authentication unit tests were generated by capturing the HTTP
5476// requests and responses using Fiddler 2 and inspecting the generated random
5477// bytes in the debugger.
5478
5479// Enter the correct password and authenticate successfully.
[email protected]23e482282013-06-14 16:08:025480TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:425481 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:245482 request.method = "GET";
5483 request.url = GURL("http://172.22.68.17/kids/login.aspx");
[email protected]2217aa22013-10-11 03:03:545484
5485 // Ensure load is not disrupted by flags which suppress behaviour specific
5486 // to other auth schemes.
5487 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:245488
[email protected]cb9bf6ca2011-01-28 13:15:275489 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
5490 MockGetHostName);
mmenkee65e7af2015-10-13 17:16:425491 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275492
[email protected]3f918782009-02-28 01:29:245493 MockWrite data_writes1[] = {
5494 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5495 "Host: 172.22.68.17\r\n"
5496 "Connection: keep-alive\r\n\r\n"),
5497 };
5498
5499 MockRead data_reads1[] = {
5500 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:045501 // Negotiate and NTLM are often requested together. However, we only want
5502 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
5503 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:245504 MockRead("WWW-Authenticate: NTLM\r\n"),
5505 MockRead("Connection: close\r\n"),
5506 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365507 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245508 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065509 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:245510 };
5511
5512 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:225513 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:245514 // request we should be issuing -- the final header line contains a Type
5515 // 1 message.
5516 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5517 "Host: 172.22.68.17\r\n"
5518 "Connection: keep-alive\r\n"
5519 "Authorization: NTLM "
5520 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5521
5522 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5523 // (the credentials for the origin server). The second request continues
5524 // on the same connection.
5525 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5526 "Host: 172.22.68.17\r\n"
5527 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:295528 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5529 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5530 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
5531 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
5532 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245533 };
5534
5535 MockRead data_reads2[] = {
5536 // The origin server responds with a Type 2 message.
5537 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5538 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:295539 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:245540 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5541 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5542 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5543 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5544 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5545 "BtAAAAAAA=\r\n"),
5546 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365547 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245548 MockRead("You are not authorized to view this page\r\n"),
5549
5550 // Lastly we get the desired content.
5551 MockRead("HTTP/1.1 200 OK\r\n"),
5552 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
5553 MockRead("Content-Length: 13\r\n\r\n"),
5554 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:065555 MockRead(SYNCHRONOUS, OK),
[email protected]3f918782009-02-28 01:29:245556 };
5557
[email protected]31a2bfe2010-02-09 08:03:395558 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5559 data_writes1, arraysize(data_writes1));
5560 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5561 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:075562 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5563 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:245564
[email protected]49639fa2011-12-20 23:22:415565 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:245566
[email protected]262eec82013-03-19 21:01:365567 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505568 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505569
[email protected]49639fa2011-12-20 23:22:415570 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425571 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:245572
5573 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425574 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:245575
[email protected]0757e7702009-03-27 04:00:225576 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5577
[email protected]1c773ea12009-04-28 19:58:425578 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:045579 ASSERT_FALSE(response == NULL);
5580 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]3f918782009-02-28 01:29:245581
[email protected]49639fa2011-12-20 23:22:415582 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:255583
[email protected]f3cf9802011-10-28 18:44:585584 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:415585 callback2.callback());
[email protected]10af5fe72011-01-31 16:17:255586 EXPECT_EQ(ERR_IO_PENDING, rv);
5587
5588 rv = callback2.WaitForResult();
5589 EXPECT_EQ(OK, rv);
5590
5591 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5592
5593 response = trans->GetResponseInfo();
5594 ASSERT_TRUE(response != NULL);
[email protected]10af5fe72011-01-31 16:17:255595 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5596
[email protected]49639fa2011-12-20 23:22:415597 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:245598
[email protected]49639fa2011-12-20 23:22:415599 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425600 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:245601
[email protected]0757e7702009-03-27 04:00:225602 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425603 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:245604
5605 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505606 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:245607 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5608 EXPECT_EQ(13, response->headers->GetContentLength());
5609}
5610
[email protected]385a4672009-03-11 22:21:295611// Enter a wrong password, and then the correct one.
[email protected]23e482282013-06-14 16:08:025612TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:425613 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:295614 request.method = "GET";
5615 request.url = GURL("http://172.22.68.17/kids/login.aspx");
5616 request.load_flags = 0;
5617
[email protected]cb9bf6ca2011-01-28 13:15:275618 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
5619 MockGetHostName);
mmenkee65e7af2015-10-13 17:16:425620 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275621
[email protected]385a4672009-03-11 22:21:295622 MockWrite data_writes1[] = {
5623 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5624 "Host: 172.22.68.17\r\n"
5625 "Connection: keep-alive\r\n\r\n"),
5626 };
5627
5628 MockRead data_reads1[] = {
5629 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:045630 // Negotiate and NTLM are often requested together. However, we only want
5631 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
5632 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:295633 MockRead("WWW-Authenticate: NTLM\r\n"),
5634 MockRead("Connection: close\r\n"),
5635 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365636 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295637 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065638 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:295639 };
5640
5641 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:225642 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:295643 // request we should be issuing -- the final header line contains a Type
5644 // 1 message.
5645 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5646 "Host: 172.22.68.17\r\n"
5647 "Connection: keep-alive\r\n"
5648 "Authorization: NTLM "
5649 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5650
5651 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5652 // (the credentials for the origin server). The second request continues
5653 // on the same connection.
5654 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5655 "Host: 172.22.68.17\r\n"
5656 "Connection: keep-alive\r\n"
5657 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5658 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5659 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
5660 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
5661 "4Ww7b7E=\r\n\r\n"),
5662 };
5663
5664 MockRead data_reads2[] = {
5665 // The origin server responds with a Type 2 message.
5666 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5667 MockRead("WWW-Authenticate: NTLM "
5668 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
5669 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5670 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5671 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5672 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5673 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5674 "BtAAAAAAA=\r\n"),
5675 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365676 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295677 MockRead("You are not authorized to view this page\r\n"),
5678
5679 // Wrong password.
5680 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:295681 MockRead("WWW-Authenticate: NTLM\r\n"),
5682 MockRead("Connection: close\r\n"),
5683 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365684 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295685 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065686 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:295687 };
5688
5689 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:225690 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:295691 // request we should be issuing -- the final header line contains a Type
5692 // 1 message.
5693 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5694 "Host: 172.22.68.17\r\n"
5695 "Connection: keep-alive\r\n"
5696 "Authorization: NTLM "
5697 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5698
5699 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5700 // (the credentials for the origin server). The second request continues
5701 // on the same connection.
5702 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5703 "Host: 172.22.68.17\r\n"
5704 "Connection: keep-alive\r\n"
5705 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5706 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5707 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
5708 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
5709 "+4MUm7c=\r\n\r\n"),
5710 };
5711
5712 MockRead data_reads3[] = {
5713 // The origin server responds with a Type 2 message.
5714 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5715 MockRead("WWW-Authenticate: NTLM "
5716 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
5717 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5718 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5719 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5720 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5721 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5722 "BtAAAAAAA=\r\n"),
5723 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365724 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295725 MockRead("You are not authorized to view this page\r\n"),
5726
5727 // Lastly we get the desired content.
5728 MockRead("HTTP/1.1 200 OK\r\n"),
5729 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
5730 MockRead("Content-Length: 13\r\n\r\n"),
5731 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:065732 MockRead(SYNCHRONOUS, OK),
[email protected]385a4672009-03-11 22:21:295733 };
5734
[email protected]31a2bfe2010-02-09 08:03:395735 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5736 data_writes1, arraysize(data_writes1));
5737 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5738 data_writes2, arraysize(data_writes2));
5739 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5740 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:075741 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5742 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5743 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:295744
[email protected]49639fa2011-12-20 23:22:415745 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:295746
[email protected]262eec82013-03-19 21:01:365747 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505748 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505749
[email protected]49639fa2011-12-20 23:22:415750 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425751 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:295752
5753 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425754 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:295755
[email protected]0757e7702009-03-27 04:00:225756 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:295757
[email protected]1c773ea12009-04-28 19:58:425758 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505759 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045760 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]385a4672009-03-11 22:21:295761
[email protected]49639fa2011-12-20 23:22:415762 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:295763
[email protected]0757e7702009-03-27 04:00:225764 // Enter the wrong password.
[email protected]f3cf9802011-10-28 18:44:585765 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
[email protected]49639fa2011-12-20 23:22:415766 callback2.callback());
[email protected]1c773ea12009-04-28 19:58:425767 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:295768
[email protected]10af5fe72011-01-31 16:17:255769 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425770 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:295771
[email protected]0757e7702009-03-27 04:00:225772 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:415773 TestCompletionCallback callback3;
5774 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425775 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:255776 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425777 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:225778 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5779
5780 response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:045781 ASSERT_FALSE(response == NULL);
5782 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]0757e7702009-03-27 04:00:225783
[email protected]49639fa2011-12-20 23:22:415784 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:225785
5786 // Now enter the right password.
[email protected]f3cf9802011-10-28 18:44:585787 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:415788 callback4.callback());
[email protected]10af5fe72011-01-31 16:17:255789 EXPECT_EQ(ERR_IO_PENDING, rv);
5790
5791 rv = callback4.WaitForResult();
5792 EXPECT_EQ(OK, rv);
5793
5794 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5795
[email protected]49639fa2011-12-20 23:22:415796 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:255797
5798 // One more roundtrip
[email protected]49639fa2011-12-20 23:22:415799 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
[email protected]1c773ea12009-04-28 19:58:425800 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:225801
5802 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425803 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:225804
[email protected]385a4672009-03-11 22:21:295805 response = trans->GetResponseInfo();
5806 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5807 EXPECT_EQ(13, response->headers->GetContentLength());
5808}
[email protected]ea9dc9a2009-09-05 00:43:325809#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:295810
[email protected]4ddaf2502008-10-23 18:26:195811// Test reading a server response which has only headers, and no body.
5812// After some maximum number of bytes is consumed, the transaction should
5813// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
[email protected]23e482282013-06-14 16:08:025814TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:425815 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:195816 request.method = "GET";
bncce36dca22015-04-21 22:11:235817 request.url = GURL("http://www.example.org/");
[email protected]4ddaf2502008-10-23 18:26:195818 request.load_flags = 0;
5819
mmenkee65e7af2015-10-13 17:16:425820 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275821 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:415822 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:275823
[email protected]b75b7b2f2009-10-06 00:54:535824 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:435825 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:535826 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:195827
5828 MockRead data_reads[] = {
5829 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:065830 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:195831 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:065832 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:195833 };
[email protected]31a2bfe2010-02-09 08:03:395834 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:075835 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:195836
[email protected]49639fa2011-12-20 23:22:415837 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:195838
[email protected]49639fa2011-12-20 23:22:415839 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425840 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:195841
5842 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425843 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:195844}
[email protected]f4e426b2008-11-05 00:24:495845
5846// Make sure that we don't try to reuse a TCPClientSocket when failing to
5847// establish tunnel.
5848// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]23e482282013-06-14 16:08:025849TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:235850 DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:275851 HttpRequestInfo request;
5852 request.method = "GET";
bncce36dca22015-04-21 22:11:235853 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:275854 request.load_flags = 0;
5855
[email protected]f4e426b2008-11-05 00:24:495856 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035857 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]db8f44c2008-12-13 04:52:015858
mmenkee65e7af2015-10-13 17:16:425859 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:495860
[email protected]262eec82013-03-19 21:01:365861 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505862 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f4e426b2008-11-05 00:24:495863
[email protected]f4e426b2008-11-05 00:24:495864 // Since we have proxy, should try to establish tunnel.
5865 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175866 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5867 "Host: www.example.org:443\r\n"
5868 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:495869 };
5870
[email protected]77848d12008-11-14 00:00:225871 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:495872 // connection. Usually a proxy would return 501 (not implemented),
5873 // or 200 (tunnel established).
5874 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:235875 MockRead("HTTP/1.1 404 Not Found\r\n"),
5876 MockRead("Content-Length: 10\r\n\r\n"),
5877 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:495878 };
5879
[email protected]31a2bfe2010-02-09 08:03:395880 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5881 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:075882 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:495883
[email protected]49639fa2011-12-20 23:22:415884 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:495885
[email protected]49639fa2011-12-20 23:22:415886 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425887 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:495888
5889 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425890 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:495891
[email protected]b4404c02009-04-10 16:38:525892 // Empty the current queue. This is necessary because idle sockets are
5893 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345894 base::MessageLoop::current()->RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:525895
[email protected]f4e426b2008-11-05 00:24:495896 // We now check to make sure the TCPClientSocket was not added back to
5897 // the pool.
[email protected]90499482013-06-01 00:39:505898 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:495899 trans.reset();
[email protected]2da659e2013-05-23 20:51:345900 base::MessageLoop::current()->RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:495901 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:505902 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:495903}
[email protected]372d34a2008-11-05 21:30:515904
[email protected]1b157c02009-04-21 01:55:405905// Make sure that we recycle a socket after reading all of the response body.
[email protected]23e482282013-06-14 16:08:025906TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:425907 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:405908 request.method = "GET";
bncce36dca22015-04-21 22:11:235909 request.url = GURL("http://www.example.org/");
[email protected]1b157c02009-04-21 01:55:405910 request.load_flags = 0;
5911
mmenkee65e7af2015-10-13 17:16:425912 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275913
[email protected]262eec82013-03-19 21:01:365914 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505915 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:275916
[email protected]1b157c02009-04-21 01:55:405917 MockRead data_reads[] = {
5918 // A part of the response body is received with the response headers.
5919 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5920 // The rest of the response body is received in two parts.
5921 MockRead("lo"),
5922 MockRead(" world"),
5923 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:065924 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:405925 };
5926
[email protected]31a2bfe2010-02-09 08:03:395927 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:075928 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:405929
[email protected]49639fa2011-12-20 23:22:415930 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:405931
[email protected]49639fa2011-12-20 23:22:415932 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425933 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:405934
5935 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425936 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:405937
[email protected]1c773ea12009-04-28 19:58:425938 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505939 ASSERT_TRUE(response != NULL);
[email protected]1b157c02009-04-21 01:55:405940
[email protected]90499482013-06-01 00:39:505941 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]1b157c02009-04-21 01:55:405942 std::string status_line = response->headers->GetStatusLine();
5943 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
5944
[email protected]90499482013-06-01 00:39:505945 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:405946
5947 std::string response_data;
5948 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:425949 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:405950 EXPECT_EQ("hello world", response_data);
5951
5952 // Empty the current queue. This is necessary because idle sockets are
5953 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345954 base::MessageLoop::current()->RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:405955
5956 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:505957 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:405958}
5959
[email protected]76a505b2010-08-25 06:23:005960// Make sure that we recycle a SSL socket after reading all of the response
5961// body.
[email protected]23e482282013-06-14 16:08:025962TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:005963 HttpRequestInfo request;
5964 request.method = "GET";
bncce36dca22015-04-21 22:11:235965 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:005966 request.load_flags = 0;
5967
5968 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:235969 MockWrite(
5970 "GET / HTTP/1.1\r\n"
5971 "Host: www.example.org\r\n"
5972 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:005973 };
5974
5975 MockRead data_reads[] = {
5976 MockRead("HTTP/1.1 200 OK\r\n"),
5977 MockRead("Content-Length: 11\r\n\r\n"),
5978 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:065979 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:005980 };
5981
[email protected]8ddf8322012-02-23 18:08:065982 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075983 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:005984
5985 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5986 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:075987 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:005988
[email protected]49639fa2011-12-20 23:22:415989 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:005990
mmenkee65e7af2015-10-13 17:16:425991 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:365992 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505993 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:005994
[email protected]49639fa2011-12-20 23:22:415995 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:005996
5997 EXPECT_EQ(ERR_IO_PENDING, rv);
5998 EXPECT_EQ(OK, callback.WaitForResult());
5999
6000 const HttpResponseInfo* response = trans->GetResponseInfo();
6001 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:506002 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:006003 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6004
[email protected]90499482013-06-01 00:39:506005 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006006
6007 std::string response_data;
6008 rv = ReadTransaction(trans.get(), &response_data);
6009 EXPECT_EQ(OK, rv);
6010 EXPECT_EQ("hello world", response_data);
6011
6012 // Empty the current queue. This is necessary because idle sockets are
6013 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:346014 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:006015
6016 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506017 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006018}
6019
6020// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
6021// from the pool and make sure that we recover okay.
[email protected]23e482282013-06-14 16:08:026022TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:006023 HttpRequestInfo request;
6024 request.method = "GET";
bncce36dca22015-04-21 22:11:236025 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:006026 request.load_flags = 0;
6027
6028 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:236029 MockWrite(
6030 "GET / HTTP/1.1\r\n"
6031 "Host: www.example.org\r\n"
6032 "Connection: keep-alive\r\n\r\n"),
6033 MockWrite(
6034 "GET / HTTP/1.1\r\n"
6035 "Host: www.example.org\r\n"
6036 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:006037 };
6038
6039 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:426040 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
6041 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:006042
[email protected]8ddf8322012-02-23 18:08:066043 SSLSocketDataProvider ssl(ASYNC, OK);
6044 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076045 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6046 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:006047
6048 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6049 data_writes, arraysize(data_writes));
6050 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
6051 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:076052 session_deps_.socket_factory->AddSocketDataProvider(&data);
6053 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:006054
[email protected]49639fa2011-12-20 23:22:416055 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:006056
mmenkee65e7af2015-10-13 17:16:426057 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:366058 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506059 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:006060
[email protected]49639fa2011-12-20 23:22:416061 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:006062
6063 EXPECT_EQ(ERR_IO_PENDING, rv);
6064 EXPECT_EQ(OK, callback.WaitForResult());
6065
6066 const HttpResponseInfo* response = trans->GetResponseInfo();
6067 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:506068 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:006069 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6070
[email protected]90499482013-06-01 00:39:506071 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006072
6073 std::string response_data;
6074 rv = ReadTransaction(trans.get(), &response_data);
6075 EXPECT_EQ(OK, rv);
6076 EXPECT_EQ("hello world", response_data);
6077
6078 // Empty the current queue. This is necessary because idle sockets are
6079 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:346080 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:006081
6082 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506083 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006084
6085 // Now start the second transaction, which should reuse the previous socket.
6086
[email protected]90499482013-06-01 00:39:506087 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:006088
[email protected]49639fa2011-12-20 23:22:416089 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:006090
6091 EXPECT_EQ(ERR_IO_PENDING, rv);
6092 EXPECT_EQ(OK, callback.WaitForResult());
6093
6094 response = trans->GetResponseInfo();
6095 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:506096 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:006097 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6098
[email protected]90499482013-06-01 00:39:506099 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006100
6101 rv = ReadTransaction(trans.get(), &response_data);
6102 EXPECT_EQ(OK, rv);
6103 EXPECT_EQ("hello world", response_data);
6104
6105 // Empty the current queue. This is necessary because idle sockets are
6106 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:346107 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:006108
6109 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506110 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006111}
6112
[email protected]b4404c02009-04-10 16:38:526113// Make sure that we recycle a socket after a zero-length response.
6114// http://crbug.com/9880
[email protected]23e482282013-06-14 16:08:026115TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:426116 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:526117 request.method = "GET";
bncce36dca22015-04-21 22:11:236118 request.url = GURL(
6119 "http://www.example.org/csi?v=3&s=web&action=&"
6120 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
6121 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
6122 "rt=prt.2642,ol.2649,xjs.2951");
[email protected]b4404c02009-04-10 16:38:526123 request.load_flags = 0;
6124
mmenkee65e7af2015-10-13 17:16:426125 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276126
[email protected]b4404c02009-04-10 16:38:526127 MockRead data_reads[] = {
6128 MockRead("HTTP/1.1 204 No Content\r\n"
6129 "Content-Length: 0\r\n"
6130 "Content-Type: text/html\r\n\r\n"),
6131 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:066132 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:526133 };
6134
[email protected]31a2bfe2010-02-09 08:03:396135 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:076136 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:526137
mmenkecc2298e2015-12-07 18:20:186138 // Transaction must be created after the MockReads, so it's destroyed before
6139 // them.
6140 scoped_ptr<HttpTransaction> trans(
6141 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6142
[email protected]49639fa2011-12-20 23:22:416143 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:526144
[email protected]49639fa2011-12-20 23:22:416145 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426146 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:526147
6148 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426149 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:526150
[email protected]1c773ea12009-04-28 19:58:426151 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506152 ASSERT_TRUE(response != NULL);
[email protected]b4404c02009-04-10 16:38:526153
[email protected]90499482013-06-01 00:39:506154 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]b4404c02009-04-10 16:38:526155 std::string status_line = response->headers->GetStatusLine();
6156 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
6157
[email protected]90499482013-06-01 00:39:506158 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:526159
6160 std::string response_data;
6161 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:426162 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:526163 EXPECT_EQ("", response_data);
6164
6165 // Empty the current queue. This is necessary because idle sockets are
6166 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:346167 base::MessageLoop::current()->RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:526168
6169 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506170 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:526171}
6172
[email protected]23e482282013-06-14 16:08:026173TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
olli.raula6df48b2a2015-11-26 07:40:226174 std::vector<scoped_ptr<UploadElementReader>> element_readers;
6175 element_readers.push_back(
6176 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
6177 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:276178
[email protected]1c773ea12009-04-28 19:58:426179 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:516180 // Transaction 1: a GET request that succeeds. The socket is recycled
6181 // after use.
6182 request[0].method = "GET";
6183 request[0].url = GURL("http://www.google.com/");
6184 request[0].load_flags = 0;
6185 // Transaction 2: a POST request. Reuses the socket kept alive from
6186 // transaction 1. The first attempts fails when writing the POST data.
6187 // This causes the transaction to retry with a new socket. The second
6188 // attempt succeeds.
6189 request[1].method = "POST";
6190 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:276191 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:516192 request[1].load_flags = 0;
6193
mmenkee65e7af2015-10-13 17:16:426194 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:516195
6196 // The first socket is used for transaction 1 and the first attempt of
6197 // transaction 2.
6198
6199 // The response of transaction 1.
6200 MockRead data_reads1[] = {
6201 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
6202 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066203 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:516204 };
6205 // The mock write results of transaction 1 and the first attempt of
6206 // transaction 2.
6207 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:066208 MockWrite(SYNCHRONOUS, 64), // GET
6209 MockWrite(SYNCHRONOUS, 93), // POST
6210 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:516211 };
[email protected]31a2bfe2010-02-09 08:03:396212 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6213 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:516214
6215 // The second socket is used for the second attempt of transaction 2.
6216
6217 // The response of transaction 2.
6218 MockRead data_reads2[] = {
6219 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
6220 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:066221 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:516222 };
6223 // The mock write results of the second attempt of transaction 2.
6224 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:066225 MockWrite(SYNCHRONOUS, 93), // POST
6226 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:516227 };
[email protected]31a2bfe2010-02-09 08:03:396228 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6229 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:516230
[email protected]bb88e1d32013-05-03 23:11:076231 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6232 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:516233
thestig9d3bb0c2015-01-24 00:49:516234 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:516235 "hello world", "welcome"
6236 };
6237
6238 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:426239 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506240 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]372d34a2008-11-05 21:30:516241
[email protected]49639fa2011-12-20 23:22:416242 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:516243
[email protected]49639fa2011-12-20 23:22:416244 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426245 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:516246
6247 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426248 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:516249
[email protected]1c773ea12009-04-28 19:58:426250 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506251 ASSERT_TRUE(response != NULL);
[email protected]372d34a2008-11-05 21:30:516252
[email protected]90499482013-06-01 00:39:506253 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]372d34a2008-11-05 21:30:516254 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6255
6256 std::string response_data;
6257 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:426258 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:516259 EXPECT_EQ(kExpectedResponseData[i], response_data);
6260 }
6261}
[email protected]f9ee6b52008-11-08 06:46:236262
6263// Test the request-challenge-retry sequence for basic auth when there is
6264// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:166265// it fails the identity from the URL is used to answer the challenge.
[email protected]23e482282013-06-14 16:08:026266TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:426267 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236268 request.method = "GET";
bncce36dca22015-04-21 22:11:236269 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:416270 request.load_flags = LOAD_NORMAL;
[email protected]a97cca42009-08-14 01:00:296271
mmenkee65e7af2015-10-13 17:16:426272 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276273 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416274 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276275
[email protected]a97cca42009-08-14 01:00:296276 // The password contains an escaped character -- for this test to pass it
6277 // will need to be unescaped by HttpNetworkTransaction.
6278 EXPECT_EQ("b%40r", request.url.password());
6279
[email protected]f9ee6b52008-11-08 06:46:236280 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236281 MockWrite(
6282 "GET / HTTP/1.1\r\n"
6283 "Host: www.example.org\r\n"
6284 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236285 };
6286
6287 MockRead data_reads1[] = {
6288 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6289 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6290 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066291 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236292 };
6293
[email protected]2262e3a2012-05-22 16:08:166294 // After the challenge above, the transaction will be restarted using the
6295 // identity from the url (foo, b@r) to answer the challenge.
6296 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236297 MockWrite(
6298 "GET / HTTP/1.1\r\n"
6299 "Host: www.example.org\r\n"
6300 "Connection: keep-alive\r\n"
6301 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166302 };
6303
6304 MockRead data_reads2[] = {
6305 MockRead("HTTP/1.0 200 OK\r\n"),
6306 MockRead("Content-Length: 100\r\n\r\n"),
6307 MockRead(SYNCHRONOUS, OK),
6308 };
6309
[email protected]31a2bfe2010-02-09 08:03:396310 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6311 data_writes1, arraysize(data_writes1));
[email protected]2262e3a2012-05-22 16:08:166312 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6313 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076314 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6315 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236316
[email protected]49639fa2011-12-20 23:22:416317 TestCompletionCallback callback1;
[email protected]49639fa2011-12-20 23:22:416318 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426319 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236320 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426321 EXPECT_EQ(OK, rv);
[email protected]2262e3a2012-05-22 16:08:166322 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6323
6324 TestCompletionCallback callback2;
6325 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6326 EXPECT_EQ(ERR_IO_PENDING, rv);
6327 rv = callback2.WaitForResult();
6328 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226329 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6330
[email protected]2262e3a2012-05-22 16:08:166331 const HttpResponseInfo* response = trans->GetResponseInfo();
6332 ASSERT_TRUE(response != NULL);
6333
6334 // There is no challenge info, since the identity in URL worked.
6335 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6336
6337 EXPECT_EQ(100, response->headers->GetContentLength());
6338
6339 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:346340 base::MessageLoop::current()->RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:166341}
6342
6343// Test the request-challenge-retry sequence for basic auth when there is an
6344// incorrect identity in the URL. The identity from the URL should be used only
6345// once.
[email protected]23e482282013-06-14 16:08:026346TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:166347 HttpRequestInfo request;
6348 request.method = "GET";
6349 // Note: the URL has a username:password in it. The password "baz" is
6350 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:236351 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:166352
6353 request.load_flags = LOAD_NORMAL;
6354
mmenkee65e7af2015-10-13 17:16:426355 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2262e3a2012-05-22 16:08:166356 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416357 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2262e3a2012-05-22 16:08:166358
6359 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236360 MockWrite(
6361 "GET / HTTP/1.1\r\n"
6362 "Host: www.example.org\r\n"
6363 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166364 };
6365
6366 MockRead data_reads1[] = {
6367 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6368 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6369 MockRead("Content-Length: 10\r\n\r\n"),
6370 MockRead(SYNCHRONOUS, ERR_FAILED),
6371 };
6372
6373 // After the challenge above, the transaction will be restarted using the
6374 // identity from the url (foo, baz) to answer the challenge.
6375 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236376 MockWrite(
6377 "GET / HTTP/1.1\r\n"
6378 "Host: www.example.org\r\n"
6379 "Connection: keep-alive\r\n"
6380 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166381 };
6382
6383 MockRead data_reads2[] = {
6384 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6385 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6386 MockRead("Content-Length: 10\r\n\r\n"),
6387 MockRead(SYNCHRONOUS, ERR_FAILED),
6388 };
6389
6390 // After the challenge above, the transaction will be restarted using the
6391 // identity supplied by the user (foo, bar) to answer the challenge.
6392 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236393 MockWrite(
6394 "GET / HTTP/1.1\r\n"
6395 "Host: www.example.org\r\n"
6396 "Connection: keep-alive\r\n"
6397 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166398 };
6399
6400 MockRead data_reads3[] = {
6401 MockRead("HTTP/1.0 200 OK\r\n"),
6402 MockRead("Content-Length: 100\r\n\r\n"),
6403 MockRead(SYNCHRONOUS, OK),
6404 };
6405
6406 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6407 data_writes1, arraysize(data_writes1));
6408 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6409 data_writes2, arraysize(data_writes2));
6410 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6411 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:076412 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6413 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6414 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:166415
6416 TestCompletionCallback callback1;
6417
6418 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6419 EXPECT_EQ(ERR_IO_PENDING, rv);
6420
6421 rv = callback1.WaitForResult();
6422 EXPECT_EQ(OK, rv);
6423
6424 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6425 TestCompletionCallback callback2;
6426 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6427 EXPECT_EQ(ERR_IO_PENDING, rv);
6428 rv = callback2.WaitForResult();
6429 EXPECT_EQ(OK, rv);
6430 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6431
6432 const HttpResponseInfo* response = trans->GetResponseInfo();
6433 ASSERT_TRUE(response != NULL);
6434 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6435
6436 TestCompletionCallback callback3;
6437 rv = trans->RestartWithAuth(
6438 AuthCredentials(kFoo, kBar), callback3.callback());
6439 EXPECT_EQ(ERR_IO_PENDING, rv);
6440 rv = callback3.WaitForResult();
6441 EXPECT_EQ(OK, rv);
6442 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6443
6444 response = trans->GetResponseInfo();
6445 ASSERT_TRUE(response != NULL);
6446
6447 // There is no challenge info, since the identity worked.
6448 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6449
6450 EXPECT_EQ(100, response->headers->GetContentLength());
6451
[email protected]ea9dc9a2009-09-05 00:43:326452 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:346453 base::MessageLoop::current()->RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:326454}
6455
[email protected]2217aa22013-10-11 03:03:546456
6457// Test the request-challenge-retry sequence for basic auth when there is a
6458// correct identity in the URL, but its use is being suppressed. The identity
6459// from the URL should never be used.
6460TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
6461 HttpRequestInfo request;
6462 request.method = "GET";
bncce36dca22015-04-21 22:11:236463 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:546464 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
6465
mmenkee65e7af2015-10-13 17:16:426466 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2217aa22013-10-11 03:03:546467 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416468 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2217aa22013-10-11 03:03:546469
6470 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236471 MockWrite(
6472 "GET / HTTP/1.1\r\n"
6473 "Host: www.example.org\r\n"
6474 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:546475 };
6476
6477 MockRead data_reads1[] = {
6478 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6479 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6480 MockRead("Content-Length: 10\r\n\r\n"),
6481 MockRead(SYNCHRONOUS, ERR_FAILED),
6482 };
6483
6484 // After the challenge above, the transaction will be restarted using the
6485 // identity supplied by the user, not the one in the URL, to answer the
6486 // challenge.
6487 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236488 MockWrite(
6489 "GET / HTTP/1.1\r\n"
6490 "Host: www.example.org\r\n"
6491 "Connection: keep-alive\r\n"
6492 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:546493 };
6494
6495 MockRead data_reads3[] = {
6496 MockRead("HTTP/1.0 200 OK\r\n"),
6497 MockRead("Content-Length: 100\r\n\r\n"),
6498 MockRead(SYNCHRONOUS, OK),
6499 };
6500
6501 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6502 data_writes1, arraysize(data_writes1));
6503 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6504 data_writes3, arraysize(data_writes3));
6505 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6506 session_deps_.socket_factory->AddSocketDataProvider(&data3);
6507
6508 TestCompletionCallback callback1;
6509 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6510 EXPECT_EQ(ERR_IO_PENDING, rv);
6511 rv = callback1.WaitForResult();
6512 EXPECT_EQ(OK, rv);
6513 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6514
6515 const HttpResponseInfo* response = trans->GetResponseInfo();
6516 ASSERT_TRUE(response != NULL);
6517 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6518
6519 TestCompletionCallback callback3;
6520 rv = trans->RestartWithAuth(
6521 AuthCredentials(kFoo, kBar), callback3.callback());
6522 EXPECT_EQ(ERR_IO_PENDING, rv);
6523 rv = callback3.WaitForResult();
6524 EXPECT_EQ(OK, rv);
6525 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6526
6527 response = trans->GetResponseInfo();
6528 ASSERT_TRUE(response != NULL);
6529
6530 // There is no challenge info, since the identity worked.
6531 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6532 EXPECT_EQ(100, response->headers->GetContentLength());
6533
6534 // Empty the current queue.
6535 base::MessageLoop::current()->RunUntilIdle();
6536}
6537
[email protected]f9ee6b52008-11-08 06:46:236538// Test that previously tried username/passwords for a realm get re-used.
[email protected]23e482282013-06-14 16:08:026539TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
mmenkee65e7af2015-10-13 17:16:426540 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:236541
6542 // Transaction 1: authenticate (foo, bar) on MyRealm1
6543 {
[email protected]1c773ea12009-04-28 19:58:426544 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236545 request.method = "GET";
bncce36dca22015-04-21 22:11:236546 request.url = GURL("http://www.example.org/x/y/z");
[email protected]f9ee6b52008-11-08 06:46:236547 request.load_flags = 0;
6548
[email protected]262eec82013-03-19 21:01:366549 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506550 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276551
[email protected]f9ee6b52008-11-08 06:46:236552 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236553 MockWrite(
6554 "GET /x/y/z HTTP/1.1\r\n"
6555 "Host: www.example.org\r\n"
6556 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236557 };
6558
6559 MockRead data_reads1[] = {
6560 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6561 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6562 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066563 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236564 };
6565
6566 // Resend with authorization (username=foo, password=bar)
6567 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236568 MockWrite(
6569 "GET /x/y/z HTTP/1.1\r\n"
6570 "Host: www.example.org\r\n"
6571 "Connection: keep-alive\r\n"
6572 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236573 };
6574
6575 // Sever accepts the authorization.
6576 MockRead data_reads2[] = {
6577 MockRead("HTTP/1.0 200 OK\r\n"),
6578 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066579 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236580 };
6581
[email protected]31a2bfe2010-02-09 08:03:396582 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6583 data_writes1, arraysize(data_writes1));
6584 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6585 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076586 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6587 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236588
[email protected]49639fa2011-12-20 23:22:416589 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236590
[email protected]49639fa2011-12-20 23:22:416591 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426592 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236593
6594 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426595 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236596
[email protected]1c773ea12009-04-28 19:58:426597 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506598 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046599 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:236600
[email protected]49639fa2011-12-20 23:22:416601 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:236602
[email protected]49639fa2011-12-20 23:22:416603 rv = trans->RestartWithAuth(
6604 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426605 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236606
6607 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426608 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236609
6610 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506611 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236612 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6613 EXPECT_EQ(100, response->headers->GetContentLength());
6614 }
6615
6616 // ------------------------------------------------------------------------
6617
6618 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
6619 {
[email protected]1c773ea12009-04-28 19:58:426620 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236621 request.method = "GET";
6622 // Note that Transaction 1 was at /x/y/z, so this is in the same
6623 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:236624 request.url = GURL("http://www.example.org/x/y/a/b");
[email protected]f9ee6b52008-11-08 06:46:236625 request.load_flags = 0;
6626
[email protected]262eec82013-03-19 21:01:366627 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506628 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276629
[email protected]f9ee6b52008-11-08 06:46:236630 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236631 MockWrite(
6632 "GET /x/y/a/b HTTP/1.1\r\n"
6633 "Host: www.example.org\r\n"
6634 "Connection: keep-alive\r\n"
6635 // Send preemptive authorization for MyRealm1
6636 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236637 };
6638
6639 // The server didn't like the preemptive authorization, and
6640 // challenges us for a different realm (MyRealm2).
6641 MockRead data_reads1[] = {
6642 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6643 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
6644 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066645 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236646 };
6647
6648 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
6649 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236650 MockWrite(
6651 "GET /x/y/a/b HTTP/1.1\r\n"
6652 "Host: www.example.org\r\n"
6653 "Connection: keep-alive\r\n"
6654 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236655 };
6656
6657 // Sever accepts the authorization.
6658 MockRead data_reads2[] = {
6659 MockRead("HTTP/1.0 200 OK\r\n"),
6660 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066661 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236662 };
6663
[email protected]31a2bfe2010-02-09 08:03:396664 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6665 data_writes1, arraysize(data_writes1));
6666 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6667 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076668 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6669 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236670
[email protected]49639fa2011-12-20 23:22:416671 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236672
[email protected]49639fa2011-12-20 23:22:416673 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426674 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236675
6676 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426677 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236678
[email protected]1c773ea12009-04-28 19:58:426679 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506680 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046681 ASSERT_TRUE(response->auth_challenge.get());
6682 EXPECT_FALSE(response->auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:236683 EXPECT_EQ("www.example.org:80",
[email protected]79cb5c12011-09-12 13:12:046684 response->auth_challenge->challenger.ToString());
6685 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:196686 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:236687
[email protected]49639fa2011-12-20 23:22:416688 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:236689
[email protected]49639fa2011-12-20 23:22:416690 rv = trans->RestartWithAuth(
6691 AuthCredentials(kFoo2, kBar2), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426692 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236693
6694 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426695 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236696
6697 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506698 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236699 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6700 EXPECT_EQ(100, response->headers->GetContentLength());
6701 }
6702
6703 // ------------------------------------------------------------------------
6704
6705 // Transaction 3: Resend a request in MyRealm's protection space --
6706 // succeed with preemptive authorization.
6707 {
[email protected]1c773ea12009-04-28 19:58:426708 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236709 request.method = "GET";
bncce36dca22015-04-21 22:11:236710 request.url = GURL("http://www.example.org/x/y/z2");
[email protected]f9ee6b52008-11-08 06:46:236711 request.load_flags = 0;
6712
[email protected]262eec82013-03-19 21:01:366713 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506714 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276715
[email protected]f9ee6b52008-11-08 06:46:236716 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236717 MockWrite(
6718 "GET /x/y/z2 HTTP/1.1\r\n"
6719 "Host: www.example.org\r\n"
6720 "Connection: keep-alive\r\n"
6721 // The authorization for MyRealm1 gets sent preemptively
6722 // (since the url is in the same protection space)
6723 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236724 };
6725
6726 // Sever accepts the preemptive authorization
6727 MockRead data_reads1[] = {
6728 MockRead("HTTP/1.0 200 OK\r\n"),
6729 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066730 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236731 };
6732
[email protected]31a2bfe2010-02-09 08:03:396733 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6734 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:076735 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:236736
[email protected]49639fa2011-12-20 23:22:416737 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236738
[email protected]49639fa2011-12-20 23:22:416739 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426740 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236741
6742 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426743 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236744
[email protected]1c773ea12009-04-28 19:58:426745 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506746 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236747
6748 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6749 EXPECT_EQ(100, response->headers->GetContentLength());
6750 }
6751
6752 // ------------------------------------------------------------------------
6753
6754 // Transaction 4: request another URL in MyRealm (however the
6755 // url is not known to belong to the protection space, so no pre-auth).
6756 {
[email protected]1c773ea12009-04-28 19:58:426757 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236758 request.method = "GET";
bncce36dca22015-04-21 22:11:236759 request.url = GURL("http://www.example.org/x/1");
[email protected]f9ee6b52008-11-08 06:46:236760 request.load_flags = 0;
6761
[email protected]262eec82013-03-19 21:01:366762 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506763 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276764
[email protected]f9ee6b52008-11-08 06:46:236765 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236766 MockWrite(
6767 "GET /x/1 HTTP/1.1\r\n"
6768 "Host: www.example.org\r\n"
6769 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236770 };
6771
6772 MockRead data_reads1[] = {
6773 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6774 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6775 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066776 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236777 };
6778
6779 // Resend with authorization from MyRealm's cache.
6780 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236781 MockWrite(
6782 "GET /x/1 HTTP/1.1\r\n"
6783 "Host: www.example.org\r\n"
6784 "Connection: keep-alive\r\n"
6785 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236786 };
6787
6788 // Sever accepts the authorization.
6789 MockRead data_reads2[] = {
6790 MockRead("HTTP/1.0 200 OK\r\n"),
6791 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066792 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236793 };
6794
[email protected]31a2bfe2010-02-09 08:03:396795 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6796 data_writes1, arraysize(data_writes1));
6797 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6798 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076799 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6800 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236801
[email protected]49639fa2011-12-20 23:22:416802 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236803
[email protected]49639fa2011-12-20 23:22:416804 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426805 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236806
6807 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426808 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236809
[email protected]0757e7702009-03-27 04:00:226810 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:416811 TestCompletionCallback callback2;
6812 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426813 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:226814 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426815 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226816 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6817
[email protected]1c773ea12009-04-28 19:58:426818 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506819 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236820 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6821 EXPECT_EQ(100, response->headers->GetContentLength());
6822 }
6823
6824 // ------------------------------------------------------------------------
6825
6826 // Transaction 5: request a URL in MyRealm, but the server rejects the
6827 // cached identity. Should invalidate and re-prompt.
6828 {
[email protected]1c773ea12009-04-28 19:58:426829 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236830 request.method = "GET";
bncce36dca22015-04-21 22:11:236831 request.url = GURL("http://www.example.org/p/q/t");
[email protected]f9ee6b52008-11-08 06:46:236832 request.load_flags = 0;
6833
[email protected]262eec82013-03-19 21:01:366834 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506835 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276836
[email protected]f9ee6b52008-11-08 06:46:236837 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236838 MockWrite(
6839 "GET /p/q/t HTTP/1.1\r\n"
6840 "Host: www.example.org\r\n"
6841 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236842 };
6843
6844 MockRead data_reads1[] = {
6845 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6846 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6847 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066848 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236849 };
6850
6851 // Resend with authorization from cache for MyRealm.
6852 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236853 MockWrite(
6854 "GET /p/q/t HTTP/1.1\r\n"
6855 "Host: www.example.org\r\n"
6856 "Connection: keep-alive\r\n"
6857 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236858 };
6859
6860 // Sever rejects the authorization.
6861 MockRead data_reads2[] = {
6862 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6863 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6864 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066865 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236866 };
6867
6868 // At this point we should prompt for new credentials for MyRealm.
6869 // Restart with username=foo3, password=foo4.
6870 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236871 MockWrite(
6872 "GET /p/q/t HTTP/1.1\r\n"
6873 "Host: www.example.org\r\n"
6874 "Connection: keep-alive\r\n"
6875 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236876 };
6877
6878 // Sever accepts the authorization.
6879 MockRead data_reads3[] = {
6880 MockRead("HTTP/1.0 200 OK\r\n"),
6881 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066882 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236883 };
6884
[email protected]31a2bfe2010-02-09 08:03:396885 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6886 data_writes1, arraysize(data_writes1));
6887 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6888 data_writes2, arraysize(data_writes2));
6889 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6890 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:076891 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6892 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6893 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:236894
[email protected]49639fa2011-12-20 23:22:416895 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236896
[email protected]49639fa2011-12-20 23:22:416897 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426898 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236899
6900 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426901 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236902
[email protected]0757e7702009-03-27 04:00:226903 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:416904 TestCompletionCallback callback2;
6905 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426906 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:226907 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426908 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226909 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6910
[email protected]1c773ea12009-04-28 19:58:426911 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506912 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046913 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:236914
[email protected]49639fa2011-12-20 23:22:416915 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:236916
[email protected]49639fa2011-12-20 23:22:416917 rv = trans->RestartWithAuth(
6918 AuthCredentials(kFoo3, kBar3), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:426919 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236920
[email protected]0757e7702009-03-27 04:00:226921 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426922 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236923
6924 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506925 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236926 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6927 EXPECT_EQ(100, response->headers->GetContentLength());
6928 }
6929}
[email protected]89ceba9a2009-03-21 03:46:066930
[email protected]3c32c5f2010-05-18 15:18:126931// Tests that nonce count increments when multiple auth attempts
6932// are started with the same nonce.
[email protected]23e482282013-06-14 16:08:026933TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:446934 HttpAuthHandlerDigest::Factory* digest_factory =
6935 new HttpAuthHandlerDigest::Factory();
6936 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
6937 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6938 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:076939 session_deps_.http_auth_handler_factory.reset(digest_factory);
mmenkee65e7af2015-10-13 17:16:426940 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:126941
6942 // Transaction 1: authenticate (foo, bar) on MyRealm1
6943 {
[email protected]3c32c5f2010-05-18 15:18:126944 HttpRequestInfo request;
6945 request.method = "GET";
bncce36dca22015-04-21 22:11:236946 request.url = GURL("http://www.example.org/x/y/z");
[email protected]3c32c5f2010-05-18 15:18:126947 request.load_flags = 0;
6948
[email protected]262eec82013-03-19 21:01:366949 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506950 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276951
[email protected]3c32c5f2010-05-18 15:18:126952 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236953 MockWrite(
6954 "GET /x/y/z HTTP/1.1\r\n"
6955 "Host: www.example.org\r\n"
6956 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:126957 };
6958
6959 MockRead data_reads1[] = {
6960 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6961 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6962 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066963 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:126964 };
6965
6966 // Resend with authorization (username=foo, password=bar)
6967 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236968 MockWrite(
6969 "GET /x/y/z HTTP/1.1\r\n"
6970 "Host: www.example.org\r\n"
6971 "Connection: keep-alive\r\n"
6972 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6973 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6974 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6975 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:126976 };
6977
6978 // Sever accepts the authorization.
6979 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:086980 MockRead("HTTP/1.0 200 OK\r\n"),
6981 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:126982 };
6983
6984 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6985 data_writes1, arraysize(data_writes1));
6986 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6987 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076988 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6989 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:126990
[email protected]49639fa2011-12-20 23:22:416991 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:126992
[email protected]49639fa2011-12-20 23:22:416993 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:126994 EXPECT_EQ(ERR_IO_PENDING, rv);
6995
6996 rv = callback1.WaitForResult();
6997 EXPECT_EQ(OK, rv);
6998
6999 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507000 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:047001 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
[email protected]3c32c5f2010-05-18 15:18:127002
[email protected]49639fa2011-12-20 23:22:417003 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:127004
[email protected]49639fa2011-12-20 23:22:417005 rv = trans->RestartWithAuth(
7006 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]3c32c5f2010-05-18 15:18:127007 EXPECT_EQ(ERR_IO_PENDING, rv);
7008
7009 rv = callback2.WaitForResult();
7010 EXPECT_EQ(OK, rv);
7011
7012 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507013 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:127014 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7015 }
7016
7017 // ------------------------------------------------------------------------
7018
7019 // Transaction 2: Request another resource in digestive's protection space.
7020 // This will preemptively add an Authorization header which should have an
7021 // "nc" value of 2 (as compared to 1 in the first use.
7022 {
[email protected]3c32c5f2010-05-18 15:18:127023 HttpRequestInfo request;
7024 request.method = "GET";
7025 // Note that Transaction 1 was at /x/y/z, so this is in the same
7026 // protection space as digest.
bncce36dca22015-04-21 22:11:237027 request.url = GURL("http://www.example.org/x/y/a/b");
[email protected]3c32c5f2010-05-18 15:18:127028 request.load_flags = 0;
7029
[email protected]262eec82013-03-19 21:01:367030 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507031 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277032
[email protected]3c32c5f2010-05-18 15:18:127033 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237034 MockWrite(
7035 "GET /x/y/a/b HTTP/1.1\r\n"
7036 "Host: www.example.org\r\n"
7037 "Connection: keep-alive\r\n"
7038 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
7039 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
7040 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
7041 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:127042 };
7043
7044 // Sever accepts the authorization.
7045 MockRead data_reads1[] = {
7046 MockRead("HTTP/1.0 200 OK\r\n"),
7047 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067048 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:127049 };
7050
7051 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7052 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:077053 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:127054
[email protected]49639fa2011-12-20 23:22:417055 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:127056
[email protected]49639fa2011-12-20 23:22:417057 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:127058 EXPECT_EQ(ERR_IO_PENDING, rv);
7059
7060 rv = callback1.WaitForResult();
7061 EXPECT_EQ(OK, rv);
7062
7063 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507064 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:127065 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7066 }
7067}
7068
[email protected]89ceba9a2009-03-21 03:46:067069// Test the ResetStateForRestart() private method.
[email protected]23e482282013-06-14 16:08:027070TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:067071 // Create a transaction (the dependencies aren't important).
mmenkee65e7af2015-10-13 17:16:427072 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:407073 scoped_ptr<HttpNetworkTransaction> trans(
dcheng48459ac22014-08-26 00:46:417074 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]89ceba9a2009-03-21 03:46:067075
7076 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:067077 trans->read_buf_ = new IOBuffer(15);
7078 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:207079 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:067080
7081 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:147082 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:577083 response->auth_challenge = new AuthChallengeInfo();
[email protected]70d66502011-09-23 00:55:087084 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:577085 response->response_time = base::Time::Now();
7086 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:067087
7088 { // Setup state for response_.vary_data
7089 HttpRequestInfo request;
7090 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
7091 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:277092 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:437093 request.extra_headers.SetHeader("Foo", "1");
7094 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:507095 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:067096 }
7097
7098 // Cause the above state to be reset.
7099 trans->ResetStateForRestart();
7100
7101 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:077102 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:067103 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:207104 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:577105 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7106 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:047107 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:087108 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:577109 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:067110}
7111
[email protected]bacff652009-03-31 17:50:337112// Test HTTPS connections to a site with a bad certificate
[email protected]23e482282013-06-14 16:08:027113TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:337114 HttpRequestInfo request;
7115 request.method = "GET";
bncce36dca22015-04-21 22:11:237116 request.url = GURL("https://www.example.org/");
[email protected]bacff652009-03-31 17:50:337117 request.load_flags = 0;
7118
mmenkee65e7af2015-10-13 17:16:427119 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277120 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417121 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277122
[email protected]bacff652009-03-31 17:50:337123 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237124 MockWrite(
7125 "GET / HTTP/1.1\r\n"
7126 "Host: www.example.org\r\n"
7127 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337128 };
7129
7130 MockRead data_reads[] = {
7131 MockRead("HTTP/1.0 200 OK\r\n"),
7132 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7133 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067134 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:337135 };
7136
[email protected]5ecc992a42009-11-11 01:41:597137 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:397138 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7139 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067140 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7141 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:337142
[email protected]bb88e1d32013-05-03 23:11:077143 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7144 session_deps_.socket_factory->AddSocketDataProvider(&data);
7145 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7146 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:337147
[email protected]49639fa2011-12-20 23:22:417148 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:337149
[email protected]49639fa2011-12-20 23:22:417150 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:337151 EXPECT_EQ(ERR_IO_PENDING, rv);
7152
7153 rv = callback.WaitForResult();
7154 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7155
[email protected]49639fa2011-12-20 23:22:417156 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:337157 EXPECT_EQ(ERR_IO_PENDING, rv);
7158
7159 rv = callback.WaitForResult();
7160 EXPECT_EQ(OK, rv);
7161
7162 const HttpResponseInfo* response = trans->GetResponseInfo();
7163
[email protected]fe2255a2011-09-20 19:37:507164 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:337165 EXPECT_EQ(100, response->headers->GetContentLength());
7166}
7167
7168// Test HTTPS connections to a site with a bad certificate, going through a
7169// proxy
[email protected]23e482282013-06-14 16:08:027170TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
rdsmith82957ad2015-09-16 19:42:037171 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]bacff652009-03-31 17:50:337172
7173 HttpRequestInfo request;
7174 request.method = "GET";
bncce36dca22015-04-21 22:11:237175 request.url = GURL("https://www.example.org/");
[email protected]bacff652009-03-31 17:50:337176 request.load_flags = 0;
7177
7178 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:177179 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7180 "Host: www.example.org:443\r\n"
7181 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337182 };
7183
7184 MockRead proxy_reads[] = {
7185 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067186 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:337187 };
7188
7189 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177190 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7191 "Host: www.example.org:443\r\n"
7192 "Proxy-Connection: keep-alive\r\n\r\n"),
7193 MockWrite("GET / HTTP/1.1\r\n"
7194 "Host: www.example.org\r\n"
7195 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337196 };
7197
7198 MockRead data_reads[] = {
7199 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7200 MockRead("HTTP/1.0 200 OK\r\n"),
7201 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7202 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067203 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:337204 };
7205
[email protected]31a2bfe2010-02-09 08:03:397206 StaticSocketDataProvider ssl_bad_certificate(
7207 proxy_reads, arraysize(proxy_reads),
7208 proxy_writes, arraysize(proxy_writes));
7209 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7210 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067211 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7212 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:337213
[email protected]bb88e1d32013-05-03 23:11:077214 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7215 session_deps_.socket_factory->AddSocketDataProvider(&data);
7216 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7217 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:337218
[email protected]49639fa2011-12-20 23:22:417219 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:337220
7221 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:077222 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:337223
mmenkee65e7af2015-10-13 17:16:427224 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:407225 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417226 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bacff652009-03-31 17:50:337227
[email protected]49639fa2011-12-20 23:22:417228 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:337229 EXPECT_EQ(ERR_IO_PENDING, rv);
7230
7231 rv = callback.WaitForResult();
7232 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7233
[email protected]49639fa2011-12-20 23:22:417234 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:337235 EXPECT_EQ(ERR_IO_PENDING, rv);
7236
7237 rv = callback.WaitForResult();
7238 EXPECT_EQ(OK, rv);
7239
7240 const HttpResponseInfo* response = trans->GetResponseInfo();
7241
[email protected]fe2255a2011-09-20 19:37:507242 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:337243 EXPECT_EQ(100, response->headers->GetContentLength());
7244 }
7245}
7246
[email protected]2df19bb2010-08-25 20:13:467247
7248// Test HTTPS connections to a site, going through an HTTPS proxy
[email protected]23e482282013-06-14 16:08:027249TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037250 session_deps_.proxy_service =
7251 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:517252 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:077253 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:467254
7255 HttpRequestInfo request;
7256 request.method = "GET";
bncce36dca22015-04-21 22:11:237257 request.url = GURL("https://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467258 request.load_flags = 0;
7259
7260 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177261 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7262 "Host: www.example.org:443\r\n"
7263 "Proxy-Connection: keep-alive\r\n\r\n"),
7264 MockWrite("GET / HTTP/1.1\r\n"
7265 "Host: www.example.org\r\n"
7266 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467267 };
7268
7269 MockRead data_reads[] = {
7270 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7271 MockRead("HTTP/1.1 200 OK\r\n"),
7272 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7273 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067274 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467275 };
7276
7277 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7278 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067279 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
7280 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:467281
[email protected]bb88e1d32013-05-03 23:11:077282 session_deps_.socket_factory->AddSocketDataProvider(&data);
7283 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
7284 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:467285
[email protected]49639fa2011-12-20 23:22:417286 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:467287
mmenkee65e7af2015-10-13 17:16:427288 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:467289 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417290 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2df19bb2010-08-25 20:13:467291
[email protected]49639fa2011-12-20 23:22:417292 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:467293 EXPECT_EQ(ERR_IO_PENDING, rv);
7294
7295 rv = callback.WaitForResult();
7296 EXPECT_EQ(OK, rv);
7297 const HttpResponseInfo* response = trans->GetResponseInfo();
7298
[email protected]fe2255a2011-09-20 19:37:507299 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:467300
7301 EXPECT_TRUE(response->headers->IsKeepAlive());
7302 EXPECT_EQ(200, response->headers->response_code());
7303 EXPECT_EQ(100, response->headers->GetContentLength());
7304 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:207305
7306 LoadTimingInfo load_timing_info;
7307 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7308 TestLoadTimingNotReusedWithPac(load_timing_info,
7309 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:467310}
7311
[email protected]511f6f52010-12-17 03:58:297312// Test an HTTPS Proxy's ability to redirect a CONNECT request
[email protected]23e482282013-06-14 16:08:027313TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037314 session_deps_.proxy_service =
7315 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:517316 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:077317 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:297318
7319 HttpRequestInfo request;
7320 request.method = "GET";
bncce36dca22015-04-21 22:11:237321 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297322 request.load_flags = 0;
7323
7324 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177325 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7326 "Host: www.example.org:443\r\n"
7327 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:297328 };
7329
7330 MockRead data_reads[] = {
7331 MockRead("HTTP/1.1 302 Redirect\r\n"),
7332 MockRead("Location: http://login.example.com/\r\n"),
7333 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067334 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:297335 };
7336
7337 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7338 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067339 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:297340
[email protected]bb88e1d32013-05-03 23:11:077341 session_deps_.socket_factory->AddSocketDataProvider(&data);
7342 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297343
[email protected]49639fa2011-12-20 23:22:417344 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297345
mmenkee65e7af2015-10-13 17:16:427346 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297347 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417348 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297349
[email protected]49639fa2011-12-20 23:22:417350 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297351 EXPECT_EQ(ERR_IO_PENDING, rv);
7352
7353 rv = callback.WaitForResult();
7354 EXPECT_EQ(OK, rv);
7355 const HttpResponseInfo* response = trans->GetResponseInfo();
7356
[email protected]fe2255a2011-09-20 19:37:507357 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:297358
7359 EXPECT_EQ(302, response->headers->response_code());
7360 std::string url;
7361 EXPECT_TRUE(response->headers->IsRedirect(&url));
7362 EXPECT_EQ("http://login.example.com/", url);
[email protected]029c83b62013-01-24 05:28:207363
7364 // In the case of redirects from proxies, HttpNetworkTransaction returns
7365 // timing for the proxy connection instead of the connection to the host,
7366 // and no send / receive times.
7367 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
7368 LoadTimingInfo load_timing_info;
7369 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7370
7371 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:297372 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:207373
7374 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
7375 EXPECT_LE(load_timing_info.proxy_resolve_start,
7376 load_timing_info.proxy_resolve_end);
7377 EXPECT_LE(load_timing_info.proxy_resolve_end,
7378 load_timing_info.connect_timing.connect_start);
7379 ExpectConnectTimingHasTimes(
7380 load_timing_info.connect_timing,
7381 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
7382
7383 EXPECT_TRUE(load_timing_info.send_start.is_null());
7384 EXPECT_TRUE(load_timing_info.send_end.is_null());
7385 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]511f6f52010-12-17 03:58:297386}
7387
7388// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
[email protected]23e482282013-06-14 16:08:027389TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
rdsmith82957ad2015-09-16 19:42:037390 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297391
7392 HttpRequestInfo request;
7393 request.method = "GET";
bncce36dca22015-04-21 22:11:237394 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297395 request.load_flags = 0;
7396
lgarrona91df87f2014-12-05 00:51:347397 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237398 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207399 scoped_ptr<SpdyFrame> goaway(
7400 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]511f6f52010-12-17 03:58:297401 MockWrite data_writes[] = {
rch8e6c6c42015-05-01 14:05:137402 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
7403 CreateMockWrite(*goaway.get(), 2, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:297404 };
7405
7406 static const char* const kExtraHeaders[] = {
7407 "location",
7408 "http://login.example.com/",
7409 };
[email protected]ff98d7f02012-03-22 21:44:197410 scoped_ptr<SpdyFrame> resp(
[email protected]23e482282013-06-14 16:08:027411 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
[email protected]511f6f52010-12-17 03:58:297412 arraysize(kExtraHeaders)/2, 1));
7413 MockRead data_reads[] = {
rch8e6c6c42015-05-01 14:05:137414 CreateMockRead(*resp.get(), 1), MockRead(ASYNC, 0, 3), // EOF
[email protected]511f6f52010-12-17 03:58:297415 };
7416
rch8e6c6c42015-05-01 14:05:137417 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
7418 arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067419 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
rdsmithebb50aa2015-11-12 03:44:387420 proxy_ssl.SetNextProto(GetProtocol());
[email protected]511f6f52010-12-17 03:58:297421
[email protected]bb88e1d32013-05-03 23:11:077422 session_deps_.socket_factory->AddSocketDataProvider(&data);
7423 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297424
[email protected]49639fa2011-12-20 23:22:417425 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297426
mmenkee65e7af2015-10-13 17:16:427427 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297428 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417429 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297430
[email protected]49639fa2011-12-20 23:22:417431 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297432 EXPECT_EQ(ERR_IO_PENDING, rv);
7433
7434 rv = callback.WaitForResult();
7435 EXPECT_EQ(OK, rv);
7436 const HttpResponseInfo* response = trans->GetResponseInfo();
7437
[email protected]fe2255a2011-09-20 19:37:507438 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:297439
7440 EXPECT_EQ(302, response->headers->response_code());
7441 std::string url;
7442 EXPECT_TRUE(response->headers->IsRedirect(&url));
7443 EXPECT_EQ("http://login.example.com/", url);
7444}
7445
[email protected]4eddbc732012-08-09 05:40:177446// Test that an HTTPS proxy's response to a CONNECT request is filtered.
[email protected]23e482282013-06-14 16:08:027447TEST_P(HttpNetworkTransactionTest,
[email protected]4eddbc732012-08-09 05:40:177448 ErrorResponseToHttpsConnectViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037449 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297450
7451 HttpRequestInfo request;
7452 request.method = "GET";
bncce36dca22015-04-21 22:11:237453 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297454 request.load_flags = 0;
7455
7456 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177457 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7458 "Host: www.example.org:443\r\n"
7459 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:297460 };
7461
7462 MockRead data_reads[] = {
7463 MockRead("HTTP/1.1 404 Not Found\r\n"),
7464 MockRead("Content-Length: 23\r\n\r\n"),
7465 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:067466 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:297467 };
7468
7469 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7470 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067471 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:297472
[email protected]bb88e1d32013-05-03 23:11:077473 session_deps_.socket_factory->AddSocketDataProvider(&data);
7474 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297475
[email protected]49639fa2011-12-20 23:22:417476 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297477
mmenkee65e7af2015-10-13 17:16:427478 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297479 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417480 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297481
[email protected]49639fa2011-12-20 23:22:417482 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297483 EXPECT_EQ(ERR_IO_PENDING, rv);
7484
7485 rv = callback.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:177486 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]511f6f52010-12-17 03:58:297487
[email protected]4eddbc732012-08-09 05:40:177488 // TODO(ttuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:297489}
7490
[email protected]4eddbc732012-08-09 05:40:177491// Test that a SPDY proxy's response to a CONNECT request is filtered.
[email protected]23e482282013-06-14 16:08:027492TEST_P(HttpNetworkTransactionTest,
[email protected]4eddbc732012-08-09 05:40:177493 ErrorResponseToHttpsConnectViaSpdyProxy) {
rdsmith82957ad2015-09-16 19:42:037494 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297495
7496 HttpRequestInfo request;
7497 request.method = "GET";
bncce36dca22015-04-21 22:11:237498 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297499 request.load_flags = 0;
7500
lgarrona91df87f2014-12-05 00:51:347501 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237502 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207503 scoped_ptr<SpdyFrame> rst(
7504 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]511f6f52010-12-17 03:58:297505 MockWrite data_writes[] = {
rch8e6c6c42015-05-01 14:05:137506 CreateMockWrite(*conn.get(), 0), CreateMockWrite(*rst.get(), 3),
[email protected]511f6f52010-12-17 03:58:297507 };
7508
7509 static const char* const kExtraHeaders[] = {
7510 "location",
7511 "http://login.example.com/",
7512 };
[email protected]ff98d7f02012-03-22 21:44:197513 scoped_ptr<SpdyFrame> resp(
[email protected]23e482282013-06-14 16:08:027514 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
[email protected]511f6f52010-12-17 03:58:297515 arraysize(kExtraHeaders)/2, 1));
[email protected]ff98d7f02012-03-22 21:44:197516 scoped_ptr<SpdyFrame> body(
[email protected]23e482282013-06-14 16:08:027517 spdy_util_.ConstructSpdyBodyFrame(
7518 1, "The host does not exist", 23, true));
[email protected]511f6f52010-12-17 03:58:297519 MockRead data_reads[] = {
rch8e6c6c42015-05-01 14:05:137520 CreateMockRead(*resp.get(), 1),
7521 CreateMockRead(*body.get(), 2),
7522 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:297523 };
7524
rch8e6c6c42015-05-01 14:05:137525 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
7526 arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067527 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
rdsmithebb50aa2015-11-12 03:44:387528 proxy_ssl.SetNextProto(GetProtocol());
[email protected]511f6f52010-12-17 03:58:297529
[email protected]bb88e1d32013-05-03 23:11:077530 session_deps_.socket_factory->AddSocketDataProvider(&data);
7531 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297532
[email protected]49639fa2011-12-20 23:22:417533 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297534
mmenkee65e7af2015-10-13 17:16:427535 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297536 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417537 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297538
[email protected]49639fa2011-12-20 23:22:417539 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297540 EXPECT_EQ(ERR_IO_PENDING, rv);
7541
7542 rv = callback.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:177543 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]511f6f52010-12-17 03:58:297544
[email protected]4eddbc732012-08-09 05:40:177545 // TODO(ttuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:297546}
7547
[email protected]0c5fb722012-02-28 11:50:357548// Test the request-challenge-retry sequence for basic auth, through
7549// a SPDY proxy over a single SPDY session.
[email protected]23e482282013-06-14 16:08:027550TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:357551 HttpRequestInfo request;
7552 request.method = "GET";
bncce36dca22015-04-21 22:11:237553 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:357554 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:297555 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]0c5fb722012-02-28 11:50:357556
7557 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037558 session_deps_.proxy_service =
7559 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
vishal.b62985ca92015-04-17 08:45:517560 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077561 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:427562 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:357563
7564 // Since we have proxy, should try to establish tunnel.
lgarrona91df87f2014-12-05 00:51:347565 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237566 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207567 scoped_ptr<SpdyFrame> rst(
7568 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
rdsmithebb50aa2015-11-12 03:44:387569 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:357570
7571 // After calling trans->RestartWithAuth(), this is the request we should
7572 // be issuing -- the final header line contains the credentials.
7573 const char* const kAuthCredentials[] = {
7574 "proxy-authorization", "Basic Zm9vOmJhcg==",
7575 };
[email protected]fba2dbde2013-05-24 16:09:017576 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
lgarrona91df87f2014-12-05 00:51:347577 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
bncce36dca22015-04-21 22:11:237578 HostPortPair("www.example.org", 443)));
7579 // fetch https://www.example.org/ via HTTP
7580 const char get[] =
7581 "GET / HTTP/1.1\r\n"
7582 "Host: www.example.org\r\n"
7583 "Connection: keep-alive\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:197584 scoped_ptr<SpdyFrame> wrapped_get(
[email protected]23e482282013-06-14 16:08:027585 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
[email protected]0c5fb722012-02-28 11:50:357586
7587 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137588 CreateMockWrite(*req, 0, ASYNC),
7589 CreateMockWrite(*rst, 2, ASYNC),
7590 CreateMockWrite(*connect2, 3),
7591 CreateMockWrite(*wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:357592 };
7593
7594 // The proxy responds to the connect with a 407, using a persistent
7595 // connection.
thestig9d3bb0c2015-01-24 00:49:517596 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:357597 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:357598 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
7599 };
[email protected]745aa9c2014-06-27 02:21:297600 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
7601 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:357602
[email protected]23e482282013-06-14 16:08:027603 scoped_ptr<SpdyFrame> conn_resp(
7604 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]0c5fb722012-02-28 11:50:357605 const char resp[] = "HTTP/1.1 200 OK\r\n"
7606 "Content-Length: 5\r\n\r\n";
7607
[email protected]ff98d7f02012-03-22 21:44:197608 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:027609 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
[email protected]ff98d7f02012-03-22 21:44:197610 scoped_ptr<SpdyFrame> wrapped_body(
[email protected]23e482282013-06-14 16:08:027611 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
[email protected]0c5fb722012-02-28 11:50:357612 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137613 CreateMockRead(*conn_auth_resp, 1, ASYNC),
7614 CreateMockRead(*conn_resp, 4, ASYNC),
7615 CreateMockRead(*wrapped_get_resp, 6, ASYNC),
7616 CreateMockRead(*wrapped_body, 7, ASYNC),
7617 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:357618 };
7619
rch8e6c6c42015-05-01 14:05:137620 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7621 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077622 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:357623 // Negotiate SPDY to the proxy
7624 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387625 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077626 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:357627 // Vanilla SSL to the server
7628 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077629 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:357630
7631 TestCompletionCallback callback1;
7632
[email protected]262eec82013-03-19 21:01:367633 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507634 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0c5fb722012-02-28 11:50:357635
7636 int rv = trans->Start(&request, callback1.callback(), log.bound());
7637 EXPECT_EQ(ERR_IO_PENDING, rv);
7638
7639 rv = callback1.WaitForResult();
7640 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:467641 TestNetLogEntry::List entries;
[email protected]0c5fb722012-02-28 11:50:357642 log.GetEntries(&entries);
7643 size_t pos = ExpectLogContainsSomewhere(
7644 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7645 NetLog::PHASE_NONE);
7646 ExpectLogContainsSomewhere(
7647 entries, pos,
7648 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7649 NetLog::PHASE_NONE);
7650
7651 const HttpResponseInfo* response = trans->GetResponseInfo();
7652 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:507653 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]0c5fb722012-02-28 11:50:357654 EXPECT_EQ(407, response->headers->response_code());
7655 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7656 EXPECT_TRUE(response->auth_challenge.get() != NULL);
7657 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
7658
7659 TestCompletionCallback callback2;
7660
7661 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
7662 callback2.callback());
7663 EXPECT_EQ(ERR_IO_PENDING, rv);
7664
7665 rv = callback2.WaitForResult();
7666 EXPECT_EQ(OK, rv);
7667
7668 response = trans->GetResponseInfo();
7669 ASSERT_TRUE(response != NULL);
7670
7671 EXPECT_TRUE(response->headers->IsKeepAlive());
7672 EXPECT_EQ(200, response->headers->response_code());
7673 EXPECT_EQ(5, response->headers->GetContentLength());
7674 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7675
7676 // The password prompt info should not be set.
7677 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7678
[email protected]029c83b62013-01-24 05:28:207679 LoadTimingInfo load_timing_info;
7680 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7681 TestLoadTimingNotReusedWithPac(load_timing_info,
7682 CONNECT_TIMING_HAS_SSL_TIMES);
7683
[email protected]0c5fb722012-02-28 11:50:357684 trans.reset();
7685 session->CloseAllConnections();
7686}
7687
[email protected]7c6f7ba2012-04-03 04:09:297688// Test that an explicitly trusted SPDY proxy can push a resource from an
7689// origin that is different from that of its associated resource.
[email protected]23e482282013-06-14 16:08:027690TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
[email protected]7c6f7ba2012-04-03 04:09:297691 HttpRequestInfo request;
7692 HttpRequestInfo push_request;
7693
[email protected]7c6f7ba2012-04-03 04:09:297694 request.method = "GET";
bncce36dca22015-04-21 22:11:237695 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:297696 push_request.method = "GET";
7697 push_request.url = GURL("http://www.another-origin.com/foo.dat");
7698
[email protected]7c6f7ba2012-04-03 04:09:297699 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037700 session_deps_.proxy_service =
7701 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
vishal.b62985ca92015-04-17 08:45:517702 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077703 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:507704
7705 // Enable cross-origin push.
[email protected]bb88e1d32013-05-03 23:11:077706 session_deps_.trusted_spdy_proxy = "myproxy:70";
[email protected]61b4efc2012-04-27 18:12:507707
mmenkee65e7af2015-10-13 17:16:427708 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:297709
[email protected]cdf8f7e72013-05-23 10:56:467710 scoped_ptr<SpdyFrame> stream1_syn(
7711 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
[email protected]7c6f7ba2012-04-03 04:09:297712
7713 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137714 CreateMockWrite(*stream1_syn, 0, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:297715 };
7716
7717 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027718 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:297719
7720 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027721 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:297722
7723 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027724 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]7c6f7ba2012-04-03 04:09:297725 0,
7726 2,
7727 1,
7728 "http://www.another-origin.com/foo.dat"));
[email protected]8a0fc822013-06-27 20:52:437729 const char kPushedData[] = "pushed";
7730 scoped_ptr<SpdyFrame> stream2_body(
7731 spdy_util_.ConstructSpdyBodyFrame(
7732 2, kPushedData, strlen(kPushedData), true));
[email protected]7c6f7ba2012-04-03 04:09:297733
7734 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137735 CreateMockRead(*stream1_reply, 1, ASYNC),
7736 CreateMockRead(*stream2_syn, 2, ASYNC),
7737 CreateMockRead(*stream1_body, 3, ASYNC),
7738 CreateMockRead(*stream2_body, 4, ASYNC),
7739 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
[email protected]7c6f7ba2012-04-03 04:09:297740 };
7741
rch8e6c6c42015-05-01 14:05:137742 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7743 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077744 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:297745 // Negotiate SPDY to the proxy
7746 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387747 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077748 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:297749
[email protected]262eec82013-03-19 21:01:367750 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507751 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7c6f7ba2012-04-03 04:09:297752 TestCompletionCallback callback;
7753 int rv = trans->Start(&request, callback.callback(), log.bound());
7754 EXPECT_EQ(ERR_IO_PENDING, rv);
7755
7756 rv = callback.WaitForResult();
7757 EXPECT_EQ(OK, rv);
7758 const HttpResponseInfo* response = trans->GetResponseInfo();
7759
[email protected]262eec82013-03-19 21:01:367760 scoped_ptr<HttpTransaction> push_trans(
[email protected]90499482013-06-01 00:39:507761 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7762 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
[email protected]7c6f7ba2012-04-03 04:09:297763 EXPECT_EQ(ERR_IO_PENDING, rv);
7764
7765 rv = callback.WaitForResult();
7766 EXPECT_EQ(OK, rv);
7767 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
7768
7769 ASSERT_TRUE(response != NULL);
7770 EXPECT_TRUE(response->headers->IsKeepAlive());
7771
7772 EXPECT_EQ(200, response->headers->response_code());
7773 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7774
7775 std::string response_data;
7776 rv = ReadTransaction(trans.get(), &response_data);
7777 EXPECT_EQ(OK, rv);
7778 EXPECT_EQ("hello!", response_data);
7779
[email protected]029c83b62013-01-24 05:28:207780 LoadTimingInfo load_timing_info;
7781 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7782 TestLoadTimingNotReusedWithPac(load_timing_info,
7783 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7784
[email protected]7c6f7ba2012-04-03 04:09:297785 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:507786 EXPECT_TRUE(push_response->headers.get() != NULL);
[email protected]7c6f7ba2012-04-03 04:09:297787 EXPECT_EQ(200, push_response->headers->response_code());
7788
7789 rv = ReadTransaction(push_trans.get(), &response_data);
7790 EXPECT_EQ(OK, rv);
7791 EXPECT_EQ("pushed", response_data);
7792
[email protected]029c83b62013-01-24 05:28:207793 LoadTimingInfo push_load_timing_info;
7794 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
7795 TestLoadTimingReusedWithPac(push_load_timing_info);
7796 // The transactions should share a socket ID, despite being for different
7797 // origins.
7798 EXPECT_EQ(load_timing_info.socket_log_id,
7799 push_load_timing_info.socket_log_id);
7800
[email protected]7c6f7ba2012-04-03 04:09:297801 trans.reset();
7802 push_trans.reset();
7803 session->CloseAllConnections();
7804}
7805
[email protected]8c843192012-04-05 07:15:007806// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
[email protected]23e482282013-06-14 16:08:027807TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
[email protected]8c843192012-04-05 07:15:007808 HttpRequestInfo request;
7809
7810 request.method = "GET";
bncce36dca22015-04-21 22:11:237811 request.url = GURL("http://www.example.org/");
[email protected]8c843192012-04-05 07:15:007812
[email protected]8c843192012-04-05 07:15:007813 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037814 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:517815 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077816 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:507817
7818 // Enable cross-origin push.
[email protected]bb88e1d32013-05-03 23:11:077819 session_deps_.trusted_spdy_proxy = "myproxy:70";
[email protected]61b4efc2012-04-27 18:12:507820
mmenkee65e7af2015-10-13 17:16:427821 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:007822
[email protected]cdf8f7e72013-05-23 10:56:467823 scoped_ptr<SpdyFrame> stream1_syn(
7824 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
[email protected]8c843192012-04-05 07:15:007825
7826 scoped_ptr<SpdyFrame> push_rst(
[email protected]c10b20852013-05-15 21:29:207827 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:007828
7829 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137830 CreateMockWrite(*stream1_syn, 0, ASYNC), CreateMockWrite(*push_rst, 3),
[email protected]8c843192012-04-05 07:15:007831 };
7832
7833 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027834 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8c843192012-04-05 07:15:007835
7836 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027837 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]8c843192012-04-05 07:15:007838
7839 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027840 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]8c843192012-04-05 07:15:007841 0,
7842 2,
7843 1,
7844 "https://www.another-origin.com/foo.dat"));
7845
7846 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137847 CreateMockRead(*stream1_reply, 1, ASYNC),
7848 CreateMockRead(*stream2_syn, 2, ASYNC),
7849 CreateMockRead(*stream1_body, 4, ASYNC),
7850 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
[email protected]8c843192012-04-05 07:15:007851 };
7852
rch8e6c6c42015-05-01 14:05:137853 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7854 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077855 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:007856 // Negotiate SPDY to the proxy
7857 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387858 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077859 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:007860
[email protected]262eec82013-03-19 21:01:367861 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507862 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c843192012-04-05 07:15:007863 TestCompletionCallback callback;
7864 int rv = trans->Start(&request, callback.callback(), log.bound());
7865 EXPECT_EQ(ERR_IO_PENDING, rv);
7866
7867 rv = callback.WaitForResult();
7868 EXPECT_EQ(OK, rv);
7869 const HttpResponseInfo* response = trans->GetResponseInfo();
7870
7871 ASSERT_TRUE(response != NULL);
7872 EXPECT_TRUE(response->headers->IsKeepAlive());
7873
7874 EXPECT_EQ(200, response->headers->response_code());
7875 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7876
7877 std::string response_data;
7878 rv = ReadTransaction(trans.get(), &response_data);
7879 EXPECT_EQ(OK, rv);
7880 EXPECT_EQ("hello!", response_data);
7881
7882 trans.reset();
7883 session->CloseAllConnections();
7884}
7885
[email protected]2df19bb2010-08-25 20:13:467886// Test HTTPS connections to a site with a bad certificate, going through an
7887// HTTPS proxy
[email protected]23e482282013-06-14 16:08:027888TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037889 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]2df19bb2010-08-25 20:13:467890
7891 HttpRequestInfo request;
7892 request.method = "GET";
bncce36dca22015-04-21 22:11:237893 request.url = GURL("https://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467894 request.load_flags = 0;
7895
7896 // Attempt to fetch the URL from a server with a bad cert
7897 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:177898 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7899 "Host: www.example.org:443\r\n"
7900 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467901 };
7902
7903 MockRead bad_cert_reads[] = {
7904 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067905 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:467906 };
7907
7908 // Attempt to fetch the URL with a good cert
7909 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177910 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7911 "Host: www.example.org:443\r\n"
7912 "Proxy-Connection: keep-alive\r\n\r\n"),
7913 MockWrite("GET / HTTP/1.1\r\n"
7914 "Host: www.example.org\r\n"
7915 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467916 };
7917
7918 MockRead good_cert_reads[] = {
7919 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7920 MockRead("HTTP/1.0 200 OK\r\n"),
7921 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7922 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067923 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467924 };
7925
7926 StaticSocketDataProvider ssl_bad_certificate(
7927 bad_cert_reads, arraysize(bad_cert_reads),
7928 bad_cert_writes, arraysize(bad_cert_writes));
7929 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
7930 good_data_writes, arraysize(good_data_writes));
[email protected]8ddf8322012-02-23 18:08:067931 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7932 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:467933
7934 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:077935 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7936 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7937 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:467938
7939 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:077940 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7941 session_deps_.socket_factory->AddSocketDataProvider(&data);
7942 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:467943
[email protected]49639fa2011-12-20 23:22:417944 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:467945
mmenkee65e7af2015-10-13 17:16:427946 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:467947 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417948 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2df19bb2010-08-25 20:13:467949
[email protected]49639fa2011-12-20 23:22:417950 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:467951 EXPECT_EQ(ERR_IO_PENDING, rv);
7952
7953 rv = callback.WaitForResult();
7954 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7955
[email protected]49639fa2011-12-20 23:22:417956 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]2df19bb2010-08-25 20:13:467957 EXPECT_EQ(ERR_IO_PENDING, rv);
7958
7959 rv = callback.WaitForResult();
7960 EXPECT_EQ(OK, rv);
7961
7962 const HttpResponseInfo* response = trans->GetResponseInfo();
7963
[email protected]fe2255a2011-09-20 19:37:507964 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:467965 EXPECT_EQ(100, response->headers->GetContentLength());
7966}
7967
[email protected]23e482282013-06-14 16:08:027968TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:427969 HttpRequestInfo request;
7970 request.method = "GET";
bncce36dca22015-04-21 22:11:237971 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:437972 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7973 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:427974
mmenkee65e7af2015-10-13 17:16:427975 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277976 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417977 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277978
[email protected]1c773ea12009-04-28 19:58:427979 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237980 MockWrite(
7981 "GET / HTTP/1.1\r\n"
7982 "Host: www.example.org\r\n"
7983 "Connection: keep-alive\r\n"
7984 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:427985 };
7986
7987 // Lastly, the server responds with the actual content.
7988 MockRead data_reads[] = {
7989 MockRead("HTTP/1.0 200 OK\r\n"),
7990 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7991 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067992 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:427993 };
7994
[email protected]31a2bfe2010-02-09 08:03:397995 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7996 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:077997 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:427998
[email protected]49639fa2011-12-20 23:22:417999 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428000
[email protected]49639fa2011-12-20 23:22:418001 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428002 EXPECT_EQ(ERR_IO_PENDING, rv);
8003
8004 rv = callback.WaitForResult();
8005 EXPECT_EQ(OK, rv);
8006}
8007
[email protected]23e482282013-06-14 16:08:028008TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:298009 HttpRequestInfo request;
8010 request.method = "GET";
bncce36dca22015-04-21 22:11:238011 request.url = GURL("https://www.example.org/");
[email protected]da81f132010-08-18 23:39:298012 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
8013 "Chromium Ultra Awesome X Edition");
8014
rdsmith82957ad2015-09-16 19:42:038015 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:428016 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278017 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418018 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278019
[email protected]da81f132010-08-18 23:39:298020 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:178021 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8022 "Host: www.example.org:443\r\n"
8023 "Proxy-Connection: keep-alive\r\n"
8024 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]da81f132010-08-18 23:39:298025 };
8026 MockRead data_reads[] = {
8027 // Return an error, so the transaction stops here (this test isn't
8028 // interested in the rest).
8029 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
8030 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8031 MockRead("Proxy-Connection: close\r\n\r\n"),
8032 };
8033
8034 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8035 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078036 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:298037
[email protected]49639fa2011-12-20 23:22:418038 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:298039
[email protected]49639fa2011-12-20 23:22:418040 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]da81f132010-08-18 23:39:298041 EXPECT_EQ(ERR_IO_PENDING, rv);
8042
8043 rv = callback.WaitForResult();
8044 EXPECT_EQ(OK, rv);
8045}
8046
[email protected]23e482282013-06-14 16:08:028047TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:428048 HttpRequestInfo request;
8049 request.method = "GET";
bncce36dca22015-04-21 22:11:238050 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428051 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:168052 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
8053 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:428054
mmenkee65e7af2015-10-13 17:16:428055 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278056 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418057 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278058
[email protected]1c773ea12009-04-28 19:58:428059 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238060 MockWrite(
8061 "GET / HTTP/1.1\r\n"
8062 "Host: www.example.org\r\n"
8063 "Connection: keep-alive\r\n"
8064 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428065 };
8066
8067 // Lastly, the server responds with the actual content.
8068 MockRead data_reads[] = {
8069 MockRead("HTTP/1.0 200 OK\r\n"),
8070 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8071 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068072 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428073 };
8074
[email protected]31a2bfe2010-02-09 08:03:398075 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8076 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078077 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428078
[email protected]49639fa2011-12-20 23:22:418079 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428080
[email protected]49639fa2011-12-20 23:22:418081 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428082 EXPECT_EQ(ERR_IO_PENDING, rv);
8083
8084 rv = callback.WaitForResult();
8085 EXPECT_EQ(OK, rv);
8086}
8087
[email protected]23e482282013-06-14 16:08:028088TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428089 HttpRequestInfo request;
8090 request.method = "POST";
bncce36dca22015-04-21 22:11:238091 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428092
mmenkee65e7af2015-10-13 17:16:428093 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278094 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418095 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278096
[email protected]1c773ea12009-04-28 19:58:428097 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238098 MockWrite(
8099 "POST / HTTP/1.1\r\n"
8100 "Host: www.example.org\r\n"
8101 "Connection: keep-alive\r\n"
8102 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428103 };
8104
8105 // Lastly, the server responds with the actual content.
8106 MockRead data_reads[] = {
8107 MockRead("HTTP/1.0 200 OK\r\n"),
8108 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8109 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068110 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428111 };
8112
[email protected]31a2bfe2010-02-09 08:03:398113 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8114 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078115 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428116
[email protected]49639fa2011-12-20 23:22:418117 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428118
[email protected]49639fa2011-12-20 23:22:418119 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428120 EXPECT_EQ(ERR_IO_PENDING, rv);
8121
8122 rv = callback.WaitForResult();
8123 EXPECT_EQ(OK, rv);
8124}
8125
[email protected]23e482282013-06-14 16:08:028126TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428127 HttpRequestInfo request;
8128 request.method = "PUT";
bncce36dca22015-04-21 22:11:238129 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428130
mmenkee65e7af2015-10-13 17:16:428131 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278132 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418133 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278134
[email protected]1c773ea12009-04-28 19:58:428135 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238136 MockWrite(
8137 "PUT / HTTP/1.1\r\n"
8138 "Host: www.example.org\r\n"
8139 "Connection: keep-alive\r\n"
8140 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428141 };
8142
8143 // Lastly, the server responds with the actual content.
8144 MockRead data_reads[] = {
8145 MockRead("HTTP/1.0 200 OK\r\n"),
8146 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8147 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068148 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428149 };
8150
[email protected]31a2bfe2010-02-09 08:03:398151 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8152 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078153 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428154
[email protected]49639fa2011-12-20 23:22:418155 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428156
[email protected]49639fa2011-12-20 23:22:418157 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428158 EXPECT_EQ(ERR_IO_PENDING, rv);
8159
8160 rv = callback.WaitForResult();
8161 EXPECT_EQ(OK, rv);
8162}
8163
[email protected]23e482282013-06-14 16:08:028164TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428165 HttpRequestInfo request;
8166 request.method = "HEAD";
bncce36dca22015-04-21 22:11:238167 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428168
mmenkee65e7af2015-10-13 17:16:428169 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278170 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418171 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278172
[email protected]1c773ea12009-04-28 19:58:428173 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:138174 MockWrite("HEAD / HTTP/1.1\r\n"
8175 "Host: www.example.org\r\n"
8176 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428177 };
8178
8179 // Lastly, the server responds with the actual content.
8180 MockRead data_reads[] = {
8181 MockRead("HTTP/1.0 200 OK\r\n"),
8182 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8183 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068184 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428185 };
8186
[email protected]31a2bfe2010-02-09 08:03:398187 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8188 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078189 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428190
[email protected]49639fa2011-12-20 23:22:418191 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428192
[email protected]49639fa2011-12-20 23:22:418193 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428194 EXPECT_EQ(ERR_IO_PENDING, rv);
8195
8196 rv = callback.WaitForResult();
8197 EXPECT_EQ(OK, rv);
8198}
8199
[email protected]23e482282013-06-14 16:08:028200TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:428201 HttpRequestInfo request;
8202 request.method = "GET";
bncce36dca22015-04-21 22:11:238203 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428204 request.load_flags = LOAD_BYPASS_CACHE;
8205
mmenkee65e7af2015-10-13 17:16:428206 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278207 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418208 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278209
[email protected]1c773ea12009-04-28 19:58:428210 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238211 MockWrite(
8212 "GET / HTTP/1.1\r\n"
8213 "Host: www.example.org\r\n"
8214 "Connection: keep-alive\r\n"
8215 "Pragma: no-cache\r\n"
8216 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428217 };
8218
8219 // Lastly, the server responds with the actual content.
8220 MockRead data_reads[] = {
8221 MockRead("HTTP/1.0 200 OK\r\n"),
8222 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8223 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068224 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428225 };
8226
[email protected]31a2bfe2010-02-09 08:03:398227 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8228 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078229 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428230
[email protected]49639fa2011-12-20 23:22:418231 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428232
[email protected]49639fa2011-12-20 23:22:418233 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428234 EXPECT_EQ(ERR_IO_PENDING, rv);
8235
8236 rv = callback.WaitForResult();
8237 EXPECT_EQ(OK, rv);
8238}
8239
[email protected]23e482282013-06-14 16:08:028240TEST_P(HttpNetworkTransactionTest,
[email protected]1c773ea12009-04-28 19:58:428241 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:428242 HttpRequestInfo request;
8243 request.method = "GET";
bncce36dca22015-04-21 22:11:238244 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428245 request.load_flags = LOAD_VALIDATE_CACHE;
8246
mmenkee65e7af2015-10-13 17:16:428247 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278248 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418249 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278250
[email protected]1c773ea12009-04-28 19:58:428251 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238252 MockWrite(
8253 "GET / HTTP/1.1\r\n"
8254 "Host: www.example.org\r\n"
8255 "Connection: keep-alive\r\n"
8256 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428257 };
8258
8259 // Lastly, the server responds with the actual content.
8260 MockRead data_reads[] = {
8261 MockRead("HTTP/1.0 200 OK\r\n"),
8262 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8263 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068264 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428265 };
8266
[email protected]31a2bfe2010-02-09 08:03:398267 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8268 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078269 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428270
[email protected]49639fa2011-12-20 23:22:418271 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428272
[email protected]49639fa2011-12-20 23:22:418273 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428274 EXPECT_EQ(ERR_IO_PENDING, rv);
8275
8276 rv = callback.WaitForResult();
8277 EXPECT_EQ(OK, rv);
8278}
8279
[email protected]23e482282013-06-14 16:08:028280TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:428281 HttpRequestInfo request;
8282 request.method = "GET";
bncce36dca22015-04-21 22:11:238283 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438284 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:428285
mmenkee65e7af2015-10-13 17:16:428286 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278287 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418288 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278289
[email protected]1c773ea12009-04-28 19:58:428290 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238291 MockWrite(
8292 "GET / HTTP/1.1\r\n"
8293 "Host: www.example.org\r\n"
8294 "Connection: keep-alive\r\n"
8295 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428296 };
8297
8298 // Lastly, the server responds with the actual content.
8299 MockRead data_reads[] = {
8300 MockRead("HTTP/1.0 200 OK\r\n"),
8301 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8302 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068303 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428304 };
8305
[email protected]31a2bfe2010-02-09 08:03:398306 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8307 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078308 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428309
[email protected]49639fa2011-12-20 23:22:418310 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428311
[email protected]49639fa2011-12-20 23:22:418312 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428313 EXPECT_EQ(ERR_IO_PENDING, rv);
8314
8315 rv = callback.WaitForResult();
8316 EXPECT_EQ(OK, rv);
8317}
8318
[email protected]23e482282013-06-14 16:08:028319TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:478320 HttpRequestInfo request;
8321 request.method = "GET";
bncce36dca22015-04-21 22:11:238322 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438323 request.extra_headers.SetHeader("referer", "www.foo.com");
8324 request.extra_headers.SetHeader("hEllo", "Kitty");
8325 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:478326
mmenkee65e7af2015-10-13 17:16:428327 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278328 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418329 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278330
[email protected]270c6412010-03-29 22:02:478331 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238332 MockWrite(
8333 "GET / HTTP/1.1\r\n"
8334 "Host: www.example.org\r\n"
8335 "Connection: keep-alive\r\n"
8336 "referer: www.foo.com\r\n"
8337 "hEllo: Kitty\r\n"
8338 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:478339 };
8340
8341 // Lastly, the server responds with the actual content.
8342 MockRead data_reads[] = {
8343 MockRead("HTTP/1.0 200 OK\r\n"),
8344 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8345 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068346 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:478347 };
8348
8349 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8350 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078351 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:478352
[email protected]49639fa2011-12-20 23:22:418353 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:478354
[email protected]49639fa2011-12-20 23:22:418355 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]270c6412010-03-29 22:02:478356 EXPECT_EQ(ERR_IO_PENDING, rv);
8357
8358 rv = callback.WaitForResult();
8359 EXPECT_EQ(OK, rv);
8360}
8361
[email protected]23e482282013-06-14 16:08:028362TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278363 HttpRequestInfo request;
8364 request.method = "GET";
bncce36dca22015-04-21 22:11:238365 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278366 request.load_flags = 0;
8367
rdsmith82957ad2015-09-16 19:42:038368 session_deps_.proxy_service =
8369 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518370 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078371 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028372
mmenkee65e7af2015-10-13 17:16:428373 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3cd17242009-06-23 02:59:028374 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418375 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028376
[email protected]3cd17242009-06-23 02:59:028377 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8378 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8379
8380 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238381 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8382 MockWrite(
8383 "GET / HTTP/1.1\r\n"
8384 "Host: www.example.org\r\n"
8385 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028386
8387 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:068388 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:028389 MockRead("HTTP/1.0 200 OK\r\n"),
8390 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8391 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068392 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028393 };
8394
[email protected]31a2bfe2010-02-09 08:03:398395 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8396 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078397 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028398
[email protected]49639fa2011-12-20 23:22:418399 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028400
[email protected]49639fa2011-12-20 23:22:418401 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:028402 EXPECT_EQ(ERR_IO_PENDING, rv);
8403
8404 rv = callback.WaitForResult();
8405 EXPECT_EQ(OK, rv);
8406
8407 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508408 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:028409
[email protected]029c83b62013-01-24 05:28:208410 LoadTimingInfo load_timing_info;
8411 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8412 TestLoadTimingNotReusedWithPac(load_timing_info,
8413 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8414
[email protected]3cd17242009-06-23 02:59:028415 std::string response_text;
8416 rv = ReadTransaction(trans.get(), &response_text);
8417 EXPECT_EQ(OK, rv);
8418 EXPECT_EQ("Payload", response_text);
8419}
8420
[email protected]23e482282013-06-14 16:08:028421TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278422 HttpRequestInfo request;
8423 request.method = "GET";
bncce36dca22015-04-21 22:11:238424 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278425 request.load_flags = 0;
8426
rdsmith82957ad2015-09-16 19:42:038427 session_deps_.proxy_service =
8428 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518429 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078430 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028431
mmenkee65e7af2015-10-13 17:16:428432 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3cd17242009-06-23 02:59:028433 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418434 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028435
[email protected]3cd17242009-06-23 02:59:028436 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
8437 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8438
8439 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238440 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
8441 arraysize(write_buffer)),
8442 MockWrite(
8443 "GET / HTTP/1.1\r\n"
8444 "Host: www.example.org\r\n"
8445 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028446
8447 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018448 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
8449 arraysize(read_buffer)),
[email protected]e0c27be2009-07-15 13:09:358450 MockRead("HTTP/1.0 200 OK\r\n"),
8451 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8452 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068453 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358454 };
8455
[email protected]31a2bfe2010-02-09 08:03:398456 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8457 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078458 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358459
[email protected]8ddf8322012-02-23 18:08:068460 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078461 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:358462
[email protected]49639fa2011-12-20 23:22:418463 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358464
[email protected]49639fa2011-12-20 23:22:418465 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:358466 EXPECT_EQ(ERR_IO_PENDING, rv);
8467
8468 rv = callback.WaitForResult();
8469 EXPECT_EQ(OK, rv);
8470
[email protected]029c83b62013-01-24 05:28:208471 LoadTimingInfo load_timing_info;
8472 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8473 TestLoadTimingNotReusedWithPac(load_timing_info,
8474 CONNECT_TIMING_HAS_SSL_TIMES);
8475
[email protected]e0c27be2009-07-15 13:09:358476 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508477 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:358478
8479 std::string response_text;
8480 rv = ReadTransaction(trans.get(), &response_text);
8481 EXPECT_EQ(OK, rv);
8482 EXPECT_EQ("Payload", response_text);
8483}
8484
[email protected]23e482282013-06-14 16:08:028485TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:208486 HttpRequestInfo request;
8487 request.method = "GET";
bncce36dca22015-04-21 22:11:238488 request.url = GURL("http://www.example.org/");
[email protected]029c83b62013-01-24 05:28:208489 request.load_flags = 0;
8490
rdsmith82957ad2015-09-16 19:42:038491 session_deps_.proxy_service =
8492 ProxyService::CreateFixed("socks4://myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518493 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078494 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:208495
mmenkee65e7af2015-10-13 17:16:428496 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:208497 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418498 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:208499
8500 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8501 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8502
8503 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238504 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8505 MockWrite(
8506 "GET / HTTP/1.1\r\n"
8507 "Host: www.example.org\r\n"
8508 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:208509
8510 MockRead data_reads[] = {
8511 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
8512 MockRead("HTTP/1.0 200 OK\r\n"),
8513 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8514 MockRead("Payload"),
8515 MockRead(SYNCHRONOUS, OK)
8516 };
8517
8518 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8519 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078520 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:208521
8522 TestCompletionCallback callback;
8523
8524 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8525 EXPECT_EQ(ERR_IO_PENDING, rv);
8526
8527 rv = callback.WaitForResult();
8528 EXPECT_EQ(OK, rv);
8529
8530 const HttpResponseInfo* response = trans->GetResponseInfo();
8531 ASSERT_TRUE(response != NULL);
8532
8533 LoadTimingInfo load_timing_info;
8534 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8535 TestLoadTimingNotReused(load_timing_info,
8536 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8537
8538 std::string response_text;
8539 rv = ReadTransaction(trans.get(), &response_text);
8540 EXPECT_EQ(OK, rv);
8541 EXPECT_EQ("Payload", response_text);
8542}
8543
[email protected]23e482282013-06-14 16:08:028544TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278545 HttpRequestInfo request;
8546 request.method = "GET";
bncce36dca22015-04-21 22:11:238547 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278548 request.load_flags = 0;
8549
rdsmith82957ad2015-09-16 19:42:038550 session_deps_.proxy_service =
8551 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518552 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078553 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358554
mmenkee65e7af2015-10-13 17:16:428555 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e0c27be2009-07-15 13:09:358556 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418557 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358558
[email protected]e0c27be2009-07-15 13:09:358559 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8560 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378561 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238562 0x05, // Version
8563 0x01, // Command (CONNECT)
8564 0x00, // Reserved.
8565 0x03, // Address type (DOMAINNAME).
8566 0x0F, // Length of domain (15)
8567 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8568 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:378569 };
[email protected]e0c27be2009-07-15 13:09:358570 const char kSOCKS5OkResponse[] =
8571 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
8572
8573 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238574 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8575 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
8576 MockWrite(
8577 "GET / HTTP/1.1\r\n"
8578 "Host: www.example.org\r\n"
8579 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358580
8581 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018582 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8583 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]e0c27be2009-07-15 13:09:358584 MockRead("HTTP/1.0 200 OK\r\n"),
8585 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8586 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068587 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358588 };
8589
[email protected]31a2bfe2010-02-09 08:03:398590 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8591 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078592 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358593
[email protected]49639fa2011-12-20 23:22:418594 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358595
[email protected]49639fa2011-12-20 23:22:418596 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:358597 EXPECT_EQ(ERR_IO_PENDING, rv);
8598
8599 rv = callback.WaitForResult();
8600 EXPECT_EQ(OK, rv);
8601
8602 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508603 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:358604
[email protected]029c83b62013-01-24 05:28:208605 LoadTimingInfo load_timing_info;
8606 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8607 TestLoadTimingNotReusedWithPac(load_timing_info,
8608 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8609
[email protected]e0c27be2009-07-15 13:09:358610 std::string response_text;
8611 rv = ReadTransaction(trans.get(), &response_text);
8612 EXPECT_EQ(OK, rv);
8613 EXPECT_EQ("Payload", response_text);
8614}
8615
[email protected]23e482282013-06-14 16:08:028616TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278617 HttpRequestInfo request;
8618 request.method = "GET";
bncce36dca22015-04-21 22:11:238619 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278620 request.load_flags = 0;
8621
rdsmith82957ad2015-09-16 19:42:038622 session_deps_.proxy_service =
8623 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518624 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078625 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358626
mmenkee65e7af2015-10-13 17:16:428627 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e0c27be2009-07-15 13:09:358628 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418629 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358630
[email protected]e0c27be2009-07-15 13:09:358631 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8632 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378633 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238634 0x05, // Version
8635 0x01, // Command (CONNECT)
8636 0x00, // Reserved.
8637 0x03, // Address type (DOMAINNAME).
8638 0x0F, // Length of domain (15)
8639 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8640 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:378641 };
8642
[email protected]e0c27be2009-07-15 13:09:358643 const char kSOCKS5OkResponse[] =
8644 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
8645
8646 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238647 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8648 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
8649 arraysize(kSOCKS5OkRequest)),
8650 MockWrite(
8651 "GET / HTTP/1.1\r\n"
8652 "Host: www.example.org\r\n"
8653 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358654
8655 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018656 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8657 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:028658 MockRead("HTTP/1.0 200 OK\r\n"),
8659 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8660 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068661 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028662 };
8663
[email protected]31a2bfe2010-02-09 08:03:398664 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8665 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078666 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028667
[email protected]8ddf8322012-02-23 18:08:068668 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078669 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:028670
[email protected]49639fa2011-12-20 23:22:418671 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028672
[email protected]49639fa2011-12-20 23:22:418673 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:028674 EXPECT_EQ(ERR_IO_PENDING, rv);
8675
8676 rv = callback.WaitForResult();
8677 EXPECT_EQ(OK, rv);
8678
8679 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508680 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:028681
[email protected]029c83b62013-01-24 05:28:208682 LoadTimingInfo load_timing_info;
8683 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8684 TestLoadTimingNotReusedWithPac(load_timing_info,
8685 CONNECT_TIMING_HAS_SSL_TIMES);
8686
[email protected]3cd17242009-06-23 02:59:028687 std::string response_text;
8688 rv = ReadTransaction(trans.get(), &response_text);
8689 EXPECT_EQ(OK, rv);
8690 EXPECT_EQ("Payload", response_text);
8691}
8692
[email protected]448d4ca52012-03-04 04:12:238693namespace {
8694
[email protected]04e5be32009-06-26 20:00:318695// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:068696
8697struct GroupNameTest {
8698 std::string proxy_server;
8699 std::string url;
8700 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:188701 bool ssl;
[email protected]2d731a32010-04-29 01:04:068702};
8703
mmenkee65e7af2015-10-13 17:16:428704scoped_ptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8a0fc822013-06-27 20:52:438705 NextProto next_proto,
[email protected]bb88e1d32013-05-03 23:11:078706 SpdySessionDependencies* session_deps_) {
mmenkee65e7af2015-10-13 17:16:428707 scoped_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:068708
[email protected]30d4c022013-07-18 22:58:168709 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:538710 session->http_server_properties();
bnccacc0992015-03-20 20:22:228711 AlternativeService alternative_service(
bnc4988e432015-03-31 03:06:258712 AlternateProtocolFromNextProto(next_proto), "", 443);
bnc7dc7e1b42015-07-28 14:43:128713 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:228714 http_server_properties->SetAlternativeService(
bnc7dc7e1b42015-07-28 14:43:128715 HostPortPair("host.with.alternate", 80), alternative_service, 1.0,
8716 expiration);
[email protected]2d731a32010-04-29 01:04:068717
8718 return session;
8719}
8720
mmenkee65e7af2015-10-13 17:16:428721int GroupNameTransactionHelper(const std::string& url,
8722 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:068723 HttpRequestInfo request;
8724 request.method = "GET";
8725 request.url = GURL(url);
8726 request.load_flags = 0;
8727
[email protected]262eec82013-03-19 21:01:368728 scoped_ptr<HttpTransaction> trans(
mmenkee65e7af2015-10-13 17:16:428729 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
[email protected]cb9bf6ca2011-01-28 13:15:278730
[email protected]49639fa2011-12-20 23:22:418731 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:068732
8733 // We do not complete this request, the dtor will clean the transaction up.
[email protected]49639fa2011-12-20 23:22:418734 return trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d731a32010-04-29 01:04:068735}
8736
[email protected]448d4ca52012-03-04 04:12:238737} // namespace
8738
[email protected]23e482282013-06-14 16:08:028739TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
[email protected]2d731a32010-04-29 01:04:068740 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238741 {
8742 "", // unused
8743 "http://www.example.org/direct",
8744 "www.example.org:80",
8745 false,
8746 },
8747 {
8748 "", // unused
8749 "http://[2001:1418:13:1::25]/direct",
8750 "[2001:1418:13:1::25]:80",
8751 false,
8752 },
[email protected]04e5be32009-06-26 20:00:318753
bncce36dca22015-04-21 22:11:238754 // SSL Tests
8755 {
8756 "", // unused
8757 "https://www.example.org/direct_ssl",
8758 "ssl/www.example.org:443",
8759 true,
8760 },
8761 {
8762 "", // unused
8763 "https://[2001:1418:13:1::25]/direct",
8764 "ssl/[2001:1418:13:1::25]:443",
8765 true,
8766 },
8767 {
8768 "", // unused
8769 "http://host.with.alternate/direct",
8770 "ssl/host.with.alternate:443",
8771 true,
8772 },
[email protected]2d731a32010-04-29 01:04:068773 };
[email protected]2ff8b312010-04-26 22:20:548774
bnc55ff9da2015-08-19 18:42:358775 session_deps_.use_alternative_services = true;
[email protected]2d731a32010-04-29 01:04:068776
viettrungluue4a8b882014-10-16 06:17:388777 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038778 session_deps_.proxy_service =
8779 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428780 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388781 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]2d731a32010-04-29 01:04:068782
mmenkee65e7af2015-10-13 17:16:428783 HttpNetworkSessionPeer peer(session.get());
[email protected]ab739042011-04-07 15:22:288784 CaptureGroupNameTransportSocketPool* transport_conn_pool =
8785 new CaptureGroupNameTransportSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138786 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348787 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]831e4a32013-11-14 02:14:448788 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8789 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028790 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
8791 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
dchenge3d1ddc2014-10-15 19:30:518792 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
[email protected]2d731a32010-04-29 01:04:068793
8794 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428795 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188796 if (tests[i].ssl)
8797 EXPECT_EQ(tests[i].expected_group_name,
8798 ssl_conn_pool->last_group_name_received());
8799 else
8800 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:288801 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:068802 }
[email protected]2d731a32010-04-29 01:04:068803}
8804
[email protected]23e482282013-06-14 16:08:028805TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
[email protected]2d731a32010-04-29 01:04:068806 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238807 {
8808 "http_proxy",
8809 "http://www.example.org/http_proxy_normal",
8810 "www.example.org:80",
8811 false,
8812 },
[email protected]2d731a32010-04-29 01:04:068813
bncce36dca22015-04-21 22:11:238814 // SSL Tests
8815 {
8816 "http_proxy",
8817 "https://www.example.org/http_connect_ssl",
8818 "ssl/www.example.org:443",
8819 true,
8820 },
[email protected]af3490e2010-10-16 21:02:298821
bncce36dca22015-04-21 22:11:238822 {
8823 "http_proxy",
8824 "http://host.with.alternate/direct",
8825 "ssl/host.with.alternate:443",
8826 true,
8827 },
[email protected]45499252013-01-23 17:12:568828
bncce36dca22015-04-21 22:11:238829 {
8830 "http_proxy",
8831 "ftp://ftp.google.com/http_proxy_normal",
8832 "ftp/ftp.google.com:21",
8833 false,
8834 },
[email protected]2d731a32010-04-29 01:04:068835 };
8836
bnc55ff9da2015-08-19 18:42:358837 session_deps_.use_alternative_services = true;
[email protected]2d731a32010-04-29 01:04:068838
viettrungluue4a8b882014-10-16 06:17:388839 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038840 session_deps_.proxy_service =
8841 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428842 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388843 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]2d731a32010-04-29 01:04:068844
mmenkee65e7af2015-10-13 17:16:428845 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:068846
[email protected]e60e47a2010-07-14 03:37:188847 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:138848 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:348849 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138850 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348851 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:028852
[email protected]831e4a32013-11-14 02:14:448853 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8854 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028855 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
8856 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchenge3d1ddc2014-10-15 19:30:518857 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
[email protected]2d731a32010-04-29 01:04:068858
8859 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428860 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188861 if (tests[i].ssl)
8862 EXPECT_EQ(tests[i].expected_group_name,
8863 ssl_conn_pool->last_group_name_received());
8864 else
8865 EXPECT_EQ(tests[i].expected_group_name,
8866 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:068867 }
[email protected]2d731a32010-04-29 01:04:068868}
8869
[email protected]23e482282013-06-14 16:08:028870TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
[email protected]2d731a32010-04-29 01:04:068871 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238872 {
8873 "socks4://socks_proxy:1080",
8874 "http://www.example.org/socks4_direct",
8875 "socks4/www.example.org:80",
8876 false,
8877 },
8878 {
8879 "socks5://socks_proxy:1080",
8880 "http://www.example.org/socks5_direct",
8881 "socks5/www.example.org:80",
8882 false,
8883 },
[email protected]2d731a32010-04-29 01:04:068884
bncce36dca22015-04-21 22:11:238885 // SSL Tests
8886 {
8887 "socks4://socks_proxy:1080",
8888 "https://www.example.org/socks4_ssl",
8889 "socks4/ssl/www.example.org:443",
8890 true,
8891 },
8892 {
8893 "socks5://socks_proxy:1080",
8894 "https://www.example.org/socks5_ssl",
8895 "socks5/ssl/www.example.org:443",
8896 true,
8897 },
[email protected]af3490e2010-10-16 21:02:298898
bncce36dca22015-04-21 22:11:238899 {
8900 "socks4://socks_proxy:1080",
8901 "http://host.with.alternate/direct",
8902 "socks4/ssl/host.with.alternate:443",
8903 true,
8904 },
[email protected]04e5be32009-06-26 20:00:318905 };
8906
bnc55ff9da2015-08-19 18:42:358907 session_deps_.use_alternative_services = true;
[email protected]2ff8b312010-04-26 22:20:548908
viettrungluue4a8b882014-10-16 06:17:388909 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038910 session_deps_.proxy_service =
8911 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428912 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388913 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]8b114dd72011-03-25 05:33:028914
mmenkee65e7af2015-10-13 17:16:428915 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:318916
[email protected]e60e47a2010-07-14 03:37:188917 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:138918 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348919 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138920 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348921 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:028922
[email protected]831e4a32013-11-14 02:14:448923 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8924 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028925 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
8926 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchenge3d1ddc2014-10-15 19:30:518927 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
[email protected]04e5be32009-06-26 20:00:318928
[email protected]262eec82013-03-19 21:01:368929 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:508930 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]04e5be32009-06-26 20:00:318931
[email protected]2d731a32010-04-29 01:04:068932 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428933 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188934 if (tests[i].ssl)
8935 EXPECT_EQ(tests[i].expected_group_name,
8936 ssl_conn_pool->last_group_name_received());
8937 else
8938 EXPECT_EQ(tests[i].expected_group_name,
8939 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:318940 }
8941}
8942
[email protected]23e482282013-06-14 16:08:028943TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:278944 HttpRequestInfo request;
8945 request.method = "GET";
bncce36dca22015-04-21 22:11:238946 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278947
rdsmith82957ad2015-09-16 19:42:038948 session_deps_.proxy_service =
8949 ProxyService::CreateFixed("myproxy:70;foobar:80");
[email protected]b59ff372009-07-15 22:04:328950
[email protected]69719062010-01-05 20:09:218951 // This simulates failure resolving all hostnames; that means we will fail
8952 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:078953 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:328954
mmenkee65e7af2015-10-13 17:16:428955 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]9172a982009-06-06 00:30:258956 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418957 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]9172a982009-06-06 00:30:258958
[email protected]49639fa2011-12-20 23:22:418959 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:258960
[email protected]49639fa2011-12-20 23:22:418961 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9172a982009-06-06 00:30:258962 EXPECT_EQ(ERR_IO_PENDING, rv);
8963
[email protected]9172a982009-06-06 00:30:258964 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:018965 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:258966}
8967
[email protected]685af592010-05-11 19:31:248968// Base test to make sure that when the load flags for a request specify to
8969// bypass the cache, the DNS cache is not used.
[email protected]23e482282013-06-14 16:08:028970void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
[email protected]bb88e1d32013-05-03 23:11:078971 int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:278972 // Issue a request, asking to bypass the cache(s).
8973 HttpRequestInfo request;
8974 request.method = "GET";
8975 request.load_flags = load_flags;
bncce36dca22015-04-21 22:11:238976 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278977
[email protected]a2c2fb92009-07-18 07:31:048978 // Select a host resolver that does caching.
[email protected]bb88e1d32013-05-03 23:11:078979 session_deps_.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:328980
mmenkee65e7af2015-10-13 17:16:428981 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:078982 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418983 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3b9cca42009-06-16 01:08:288984
bncce36dca22015-04-21 22:11:238985 // Warm up the host cache so it has an entry for "www.example.org".
[email protected]3b9cca42009-06-16 01:08:288986 AddressList addrlist;
[email protected]aa22b242011-11-16 18:58:298987 TestCompletionCallback callback;
[email protected]bb88e1d32013-05-03 23:11:078988 int rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:238989 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8990 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:478991 EXPECT_EQ(ERR_IO_PENDING, rv);
8992 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:288993 EXPECT_EQ(OK, rv);
8994
8995 // Verify that it was added to host cache, by doing a subsequent async lookup
8996 // and confirming it completes synchronously.
[email protected]bb88e1d32013-05-03 23:11:078997 rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:238998 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8999 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:329000 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:289001
bncce36dca22015-04-21 22:11:239002 // Inject a failure the next time that "www.example.org" is resolved. This way
[email protected]3b9cca42009-06-16 01:08:289003 // we can tell if the next lookup hit the cache, or the "network".
9004 // (cache --> success, "network" --> failure).
bncce36dca22015-04-21 22:11:239005 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
[email protected]3b9cca42009-06-16 01:08:289006
9007 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
9008 // first read -- this won't be reached as the host resolution will fail first.
[email protected]8ddf8322012-02-23 18:08:069009 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:399010 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079011 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:289012
[email protected]3b9cca42009-06-16 01:08:289013 // Run the request.
[email protected]49639fa2011-12-20 23:22:419014 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:289015 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419016 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:289017
9018 // If we bypassed the cache, we would have gotten a failure while resolving
bncce36dca22015-04-21 22:11:239019 // "www.example.org".
[email protected]3b9cca42009-06-16 01:08:289020 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
9021}
9022
[email protected]685af592010-05-11 19:31:249023// There are multiple load flags that should trigger the host cache bypass.
9024// Test each in isolation:
[email protected]23e482282013-06-14 16:08:029025TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
[email protected]685af592010-05-11 19:31:249026 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
9027}
9028
[email protected]23e482282013-06-14 16:08:029029TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
[email protected]685af592010-05-11 19:31:249030 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
9031}
9032
[email protected]23e482282013-06-14 16:08:029033TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
[email protected]685af592010-05-11 19:31:249034 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
9035}
9036
[email protected]0877e3d2009-10-17 22:29:579037// Make sure we can handle an error when writing the request.
[email protected]23e482282013-06-14 16:08:029038TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:579039 HttpRequestInfo request;
9040 request.method = "GET";
9041 request.url = GURL("http://www.foo.com/");
9042 request.load_flags = 0;
9043
9044 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:069045 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:579046 };
[email protected]31a2bfe2010-02-09 08:03:399047 StaticSocketDataProvider data(NULL, 0,
9048 write_failure, arraysize(write_failure));
[email protected]bb88e1d32013-05-03 23:11:079049 session_deps_.socket_factory->AddSocketDataProvider(&data);
mmenkee65e7af2015-10-13 17:16:429050 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579051
[email protected]49639fa2011-12-20 23:22:419052 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579053
9054 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419055 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579056
[email protected]49639fa2011-12-20 23:22:419057 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579058 EXPECT_EQ(ERR_IO_PENDING, rv);
9059
9060 rv = callback.WaitForResult();
9061 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
ttuttled9dbc652015-09-29 20:00:599062
9063 IPEndPoint endpoint;
9064 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
9065 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:579066}
9067
zmo9528c9f42015-08-04 22:12:089068// Check that a connection closed after the start of the headers finishes ok.
9069TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:579070 HttpRequestInfo request;
9071 request.method = "GET";
9072 request.url = GURL("http://www.foo.com/");
9073 request.load_flags = 0;
9074
9075 MockRead data_reads[] = {
9076 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:069077 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:579078 };
9079
[email protected]31a2bfe2010-02-09 08:03:399080 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079081 session_deps_.socket_factory->AddSocketDataProvider(&data);
mmenkee65e7af2015-10-13 17:16:429082 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579083
[email protected]49639fa2011-12-20 23:22:419084 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579085
9086 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419087 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579088
[email protected]49639fa2011-12-20 23:22:419089 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579090 EXPECT_EQ(ERR_IO_PENDING, rv);
9091
9092 rv = callback.WaitForResult();
zmo9528c9f42015-08-04 22:12:089093 EXPECT_EQ(OK, rv);
9094
9095 const HttpResponseInfo* response = trans->GetResponseInfo();
9096 ASSERT_TRUE(response != NULL);
9097
9098 EXPECT_TRUE(response->headers.get() != NULL);
9099 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9100
9101 std::string response_data;
9102 rv = ReadTransaction(trans.get(), &response_data);
9103 EXPECT_EQ(OK, rv);
9104 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:599105
9106 IPEndPoint endpoint;
9107 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
9108 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:579109}
9110
9111// Make sure that a dropped connection while draining the body for auth
9112// restart does the right thing.
[email protected]23e482282013-06-14 16:08:029113TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:579114 HttpRequestInfo request;
9115 request.method = "GET";
bncce36dca22015-04-21 22:11:239116 request.url = GURL("http://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:579117 request.load_flags = 0;
9118
9119 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239120 MockWrite(
9121 "GET / HTTP/1.1\r\n"
9122 "Host: www.example.org\r\n"
9123 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:579124 };
9125
9126 MockRead data_reads1[] = {
9127 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
9128 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9129 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9130 MockRead("Content-Length: 14\r\n\r\n"),
9131 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:069132 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:579133 };
9134
[email protected]31a2bfe2010-02-09 08:03:399135 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9136 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:079137 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:579138
9139 // After calling trans->RestartWithAuth(), this is the request we should
9140 // be issuing -- the final header line contains the credentials.
9141 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239142 MockWrite(
9143 "GET / HTTP/1.1\r\n"
9144 "Host: www.example.org\r\n"
9145 "Connection: keep-alive\r\n"
9146 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:579147 };
9148
9149 // Lastly, the server responds with the actual content.
9150 MockRead data_reads2[] = {
9151 MockRead("HTTP/1.1 200 OK\r\n"),
9152 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9153 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069154 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:579155 };
9156
[email protected]31a2bfe2010-02-09 08:03:399157 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9158 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:079159 session_deps_.socket_factory->AddSocketDataProvider(&data2);
mmenkee65e7af2015-10-13 17:16:429160 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579161
[email protected]49639fa2011-12-20 23:22:419162 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:579163
[email protected]262eec82013-03-19 21:01:369164 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509165 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509166
[email protected]49639fa2011-12-20 23:22:419167 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579168 EXPECT_EQ(ERR_IO_PENDING, rv);
9169
9170 rv = callback1.WaitForResult();
9171 EXPECT_EQ(OK, rv);
9172
9173 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509174 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049175 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:579176
[email protected]49639fa2011-12-20 23:22:419177 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:579178
[email protected]49639fa2011-12-20 23:22:419179 rv = trans->RestartWithAuth(
9180 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]0877e3d2009-10-17 22:29:579181 EXPECT_EQ(ERR_IO_PENDING, rv);
9182
9183 rv = callback2.WaitForResult();
9184 EXPECT_EQ(OK, rv);
9185
9186 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509187 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:579188 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9189 EXPECT_EQ(100, response->headers->GetContentLength());
9190}
9191
9192// Test HTTPS connections going through a proxy that sends extra data.
[email protected]23e482282013-06-14 16:08:029193TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
rdsmith82957ad2015-09-16 19:42:039194 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]0877e3d2009-10-17 22:29:579195
9196 HttpRequestInfo request;
9197 request.method = "GET";
bncce36dca22015-04-21 22:11:239198 request.url = GURL("https://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:579199 request.load_flags = 0;
9200
9201 MockRead proxy_reads[] = {
9202 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:069203 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:579204 };
9205
[email protected]31a2bfe2010-02-09 08:03:399206 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]8ddf8322012-02-23 18:08:069207 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:579208
[email protected]bb88e1d32013-05-03 23:11:079209 session_deps_.socket_factory->AddSocketDataProvider(&data);
9210 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:579211
[email protected]49639fa2011-12-20 23:22:419212 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579213
[email protected]bb88e1d32013-05-03 23:11:079214 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:579215
mmenkee65e7af2015-10-13 17:16:429216 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579217 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419218 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579219
[email protected]49639fa2011-12-20 23:22:419220 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579221 EXPECT_EQ(ERR_IO_PENDING, rv);
9222
9223 rv = callback.WaitForResult();
9224 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
9225}
9226
[email protected]23e482282013-06-14 16:08:029227TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:469228 HttpRequestInfo request;
9229 request.method = "GET";
bncce36dca22015-04-21 22:11:239230 request.url = GURL("http://www.example.org/");
[email protected]9492e4a2010-02-24 00:58:469231 request.load_flags = 0;
9232
mmenkee65e7af2015-10-13 17:16:429233 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279234 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419235 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:279236
[email protected]e22e1362009-11-23 21:31:129237 MockRead data_reads[] = {
9238 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069239 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:129240 };
[email protected]9492e4a2010-02-24 00:58:469241
9242 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079243 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:469244
[email protected]49639fa2011-12-20 23:22:419245 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:469246
[email protected]49639fa2011-12-20 23:22:419247 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:469248 EXPECT_EQ(ERR_IO_PENDING, rv);
9249
9250 EXPECT_EQ(OK, callback.WaitForResult());
9251
9252 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509253 ASSERT_TRUE(response != NULL);
[email protected]9492e4a2010-02-24 00:58:469254
[email protected]90499482013-06-01 00:39:509255 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]9492e4a2010-02-24 00:58:469256 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9257
9258 std::string response_data;
9259 rv = ReadTransaction(trans.get(), &response_data);
[email protected]5543cbb2012-04-20 16:35:239260 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
[email protected]e22e1362009-11-23 21:31:129261}
9262
[email protected]23e482282013-06-14 16:08:029263TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:159264 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:529265 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
[email protected]95d88ffe2010-02-04 21:25:339266 const uint64 kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:219267 UploadFileElementReader::ScopedOverridingContentLengthForTests
9268 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:339269
olli.raula6df48b2a2015-11-26 07:40:229270 std::vector<scoped_ptr<UploadElementReader>> element_readers;
9271 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
9272 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0, kuint64max,
9273 base::Time())));
9274 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279275
9276 HttpRequestInfo request;
9277 request.method = "POST";
bncce36dca22015-04-21 22:11:239278 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279279 request.upload_data_stream = &upload_data_stream;
9280 request.load_flags = 0;
9281
mmenkee65e7af2015-10-13 17:16:429282 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]329b68b2012-11-14 17:54:279283 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419284 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]95d88ffe2010-02-04 21:25:339285
9286 MockRead data_reads[] = {
9287 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9288 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069289 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:339290 };
[email protected]31a2bfe2010-02-09 08:03:399291 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079292 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:339293
[email protected]49639fa2011-12-20 23:22:419294 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:339295
[email protected]49639fa2011-12-20 23:22:419296 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:339297 EXPECT_EQ(ERR_IO_PENDING, rv);
9298
9299 rv = callback.WaitForResult();
9300 EXPECT_EQ(OK, rv);
9301
9302 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509303 ASSERT_TRUE(response != NULL);
[email protected]95d88ffe2010-02-04 21:25:339304
[email protected]90499482013-06-01 00:39:509305 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]95d88ffe2010-02-04 21:25:339306 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9307
9308 std::string response_data;
9309 rv = ReadTransaction(trans.get(), &response_data);
9310 EXPECT_EQ(OK, rv);
9311 EXPECT_EQ("hello world", response_data);
9312
[email protected]dd3aa792013-07-16 19:10:239313 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:339314}
9315
[email protected]23e482282013-06-14 16:08:029316TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:159317 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:529318 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:369319 std::string temp_file_content("Unreadable file.");
[email protected]e5c2a22e2014-03-06 20:42:309320 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
[email protected]6624b4622010-03-29 19:58:369321 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:119322 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:369323
olli.raula6df48b2a2015-11-26 07:40:229324 std::vector<scoped_ptr<UploadElementReader>> element_readers;
9325 element_readers.push_back(make_scoped_ptr(
skyostil4891b25b2015-06-11 11:43:459326 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
olli.raula6df48b2a2015-11-26 07:40:229327 temp_file, 0, kuint64max, base::Time())));
9328 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279329
9330 HttpRequestInfo request;
9331 request.method = "POST";
bncce36dca22015-04-21 22:11:239332 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279333 request.upload_data_stream = &upload_data_stream;
9334 request.load_flags = 0;
9335
[email protected]999dd8c2013-11-12 06:45:549336 // If we try to upload an unreadable file, the transaction should fail.
mmenkee65e7af2015-10-13 17:16:429337 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]329b68b2012-11-14 17:54:279338 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419339 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]6624b4622010-03-29 19:58:369340
[email protected]999dd8c2013-11-12 06:45:549341 StaticSocketDataProvider data(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079342 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:369343
[email protected]49639fa2011-12-20 23:22:419344 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:369345
[email protected]49639fa2011-12-20 23:22:419346 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:369347 EXPECT_EQ(ERR_IO_PENDING, rv);
9348
9349 rv = callback.WaitForResult();
[email protected]999dd8c2013-11-12 06:45:549350 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
[email protected]6624b4622010-03-29 19:58:369351
[email protected]dd3aa792013-07-16 19:10:239352 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:369353}
9354
[email protected]02cad5d2013-10-02 08:14:039355TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
9356 class FakeUploadElementReader : public UploadElementReader {
9357 public:
9358 FakeUploadElementReader() {}
dchengb03027d2014-10-21 12:00:209359 ~FakeUploadElementReader() override {}
[email protected]02cad5d2013-10-02 08:14:039360
9361 const CompletionCallback& callback() const { return callback_; }
9362
9363 // UploadElementReader overrides:
dchengb03027d2014-10-21 12:00:209364 int Init(const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039365 callback_ = callback;
9366 return ERR_IO_PENDING;
9367 }
dchengb03027d2014-10-21 12:00:209368 uint64 GetContentLength() const override { return 0; }
9369 uint64 BytesRemaining() const override { return 0; }
9370 int Read(IOBuffer* buf,
9371 int buf_length,
9372 const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039373 return ERR_FAILED;
9374 }
9375
9376 private:
9377 CompletionCallback callback_;
9378 };
9379
9380 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
olli.raula6df48b2a2015-11-26 07:40:229381 std::vector<scoped_ptr<UploadElementReader>> element_readers;
9382 element_readers.push_back(make_scoped_ptr(fake_reader));
9383 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:039384
9385 HttpRequestInfo request;
9386 request.method = "POST";
bncce36dca22015-04-21 22:11:239387 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:039388 request.upload_data_stream = &upload_data_stream;
9389 request.load_flags = 0;
9390
mmenkee65e7af2015-10-13 17:16:429391 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02cad5d2013-10-02 08:14:039392 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419393 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02cad5d2013-10-02 08:14:039394
9395 StaticSocketDataProvider data;
9396 session_deps_.socket_factory->AddSocketDataProvider(&data);
9397
9398 TestCompletionCallback callback;
9399 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9400 EXPECT_EQ(ERR_IO_PENDING, rv);
9401 base::MessageLoop::current()->RunUntilIdle();
9402
9403 // Transaction is pending on request body initialization.
9404 ASSERT_FALSE(fake_reader->callback().is_null());
9405
9406 // Return Init()'s result after the transaction gets destroyed.
9407 trans.reset();
9408 fake_reader->callback().Run(OK); // Should not crash.
9409}
9410
[email protected]aeefc9e82010-02-19 16:18:279411// Tests that changes to Auth realms are treated like auth rejections.
[email protected]23e482282013-06-14 16:08:029412TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:279413 HttpRequestInfo request;
9414 request.method = "GET";
bncce36dca22015-04-21 22:11:239415 request.url = GURL("http://www.example.org/");
[email protected]aeefc9e82010-02-19 16:18:279416 request.load_flags = 0;
9417
9418 // First transaction will request a resource and receive a Basic challenge
9419 // with realm="first_realm".
9420 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239421 MockWrite(
9422 "GET / HTTP/1.1\r\n"
9423 "Host: www.example.org\r\n"
9424 "Connection: keep-alive\r\n"
9425 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279426 };
9427 MockRead data_reads1[] = {
9428 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9429 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9430 "\r\n"),
9431 };
9432
9433 // After calling trans->RestartWithAuth(), provide an Authentication header
9434 // for first_realm. The server will reject and provide a challenge with
9435 // second_realm.
9436 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239437 MockWrite(
9438 "GET / HTTP/1.1\r\n"
9439 "Host: www.example.org\r\n"
9440 "Connection: keep-alive\r\n"
9441 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
9442 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279443 };
9444 MockRead data_reads2[] = {
9445 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9446 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
9447 "\r\n"),
9448 };
9449
9450 // This again fails, and goes back to first_realm. Make sure that the
9451 // entry is removed from cache.
9452 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239453 MockWrite(
9454 "GET / HTTP/1.1\r\n"
9455 "Host: www.example.org\r\n"
9456 "Connection: keep-alive\r\n"
9457 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
9458 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279459 };
9460 MockRead data_reads3[] = {
9461 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9462 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9463 "\r\n"),
9464 };
9465
9466 // Try one last time (with the correct password) and get the resource.
9467 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:239468 MockWrite(
9469 "GET / HTTP/1.1\r\n"
9470 "Host: www.example.org\r\n"
9471 "Connection: keep-alive\r\n"
9472 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
9473 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279474 };
9475 MockRead data_reads4[] = {
9476 MockRead("HTTP/1.1 200 OK\r\n"
9477 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:509478 "Content-Length: 5\r\n"
9479 "\r\n"
9480 "hello"),
[email protected]aeefc9e82010-02-19 16:18:279481 };
9482
9483 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9484 data_writes1, arraysize(data_writes1));
9485 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9486 data_writes2, arraysize(data_writes2));
9487 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
9488 data_writes3, arraysize(data_writes3));
9489 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
9490 data_writes4, arraysize(data_writes4));
[email protected]bb88e1d32013-05-03 23:11:079491 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9492 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9493 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9494 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:279495
[email protected]49639fa2011-12-20 23:22:419496 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:279497
mmenkee65e7af2015-10-13 17:16:429498 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0b0bf032010-09-21 18:08:509499 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419500 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509501
[email protected]aeefc9e82010-02-19 16:18:279502 // Issue the first request with Authorize headers. There should be a
9503 // password prompt for first_realm waiting to be filled in after the
9504 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419505 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:279506 EXPECT_EQ(ERR_IO_PENDING, rv);
9507 rv = callback1.WaitForResult();
9508 EXPECT_EQ(OK, rv);
9509 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509510 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049511 const AuthChallengeInfo* challenge = response->auth_challenge.get();
9512 ASSERT_FALSE(challenge == NULL);
9513 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239514 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049515 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199516 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279517
9518 // Issue the second request with an incorrect password. There should be a
9519 // password prompt for second_realm waiting to be filled in after the
9520 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419521 TestCompletionCallback callback2;
9522 rv = trans->RestartWithAuth(
9523 AuthCredentials(kFirst, kBaz), callback2.callback());
[email protected]aeefc9e82010-02-19 16:18:279524 EXPECT_EQ(ERR_IO_PENDING, rv);
9525 rv = callback2.WaitForResult();
9526 EXPECT_EQ(OK, rv);
9527 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509528 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049529 challenge = response->auth_challenge.get();
9530 ASSERT_FALSE(challenge == NULL);
9531 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239532 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049533 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199534 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279535
9536 // Issue the third request with another incorrect password. There should be
9537 // a password prompt for first_realm waiting to be filled in. If the password
9538 // prompt is not present, it indicates that the HttpAuthCacheEntry for
9539 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:419540 TestCompletionCallback callback3;
9541 rv = trans->RestartWithAuth(
9542 AuthCredentials(kSecond, kFou), callback3.callback());
[email protected]aeefc9e82010-02-19 16:18:279543 EXPECT_EQ(ERR_IO_PENDING, rv);
9544 rv = callback3.WaitForResult();
9545 EXPECT_EQ(OK, rv);
9546 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509547 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049548 challenge = response->auth_challenge.get();
9549 ASSERT_FALSE(challenge == NULL);
9550 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239551 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049552 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199553 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279554
9555 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:419556 TestCompletionCallback callback4;
9557 rv = trans->RestartWithAuth(
9558 AuthCredentials(kFirst, kBar), callback4.callback());
[email protected]aeefc9e82010-02-19 16:18:279559 EXPECT_EQ(ERR_IO_PENDING, rv);
9560 rv = callback4.WaitForResult();
9561 EXPECT_EQ(OK, rv);
9562 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509563 ASSERT_TRUE(response != NULL);
[email protected]aeefc9e82010-02-19 16:18:279564 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9565}
9566
bncc958faa2015-07-31 18:14:529567TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
9568 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359569 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529570
9571 std::string alternative_service_http_header =
9572 GetAlternativeServiceHttpHeader();
9573
9574 MockRead data_reads[] = {
9575 MockRead("HTTP/1.1 200 OK\r\n"),
9576 MockRead(alternative_service_http_header.c_str()),
9577 MockRead("\r\n"),
9578 MockRead("hello world"),
9579 MockRead(SYNCHRONOUS, OK),
9580 };
9581
9582 HttpRequestInfo request;
9583 request.method = "GET";
9584 request.url = GURL("http://www.example.org/");
9585 request.load_flags = 0;
9586
9587 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9588
9589 session_deps_.socket_factory->AddSocketDataProvider(&data);
9590
9591 TestCompletionCallback callback;
9592
mmenkee65e7af2015-10-13 17:16:429593 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529594 scoped_ptr<HttpTransaction> trans(
9595 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9596
9597 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9598 EXPECT_EQ(ERR_IO_PENDING, rv);
9599
9600 HostPortPair http_host_port_pair("www.example.org", 80);
9601 HttpServerProperties& http_server_properties =
9602 *session->http_server_properties();
9603 AlternativeServiceVector alternative_service_vector =
9604 http_server_properties.GetAlternativeServices(http_host_port_pair);
9605 EXPECT_TRUE(alternative_service_vector.empty());
9606
9607 EXPECT_EQ(OK, callback.WaitForResult());
9608
9609 const HttpResponseInfo* response = trans->GetResponseInfo();
9610 ASSERT_TRUE(response != NULL);
9611 ASSERT_TRUE(response->headers.get() != NULL);
9612 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9613 EXPECT_FALSE(response->was_fetched_via_spdy);
9614 EXPECT_FALSE(response->was_npn_negotiated);
9615
9616 std::string response_data;
9617 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9618 EXPECT_EQ("hello world", response_data);
9619
9620 alternative_service_vector =
9621 http_server_properties.GetAlternativeServices(http_host_port_pair);
9622 ASSERT_EQ(1u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389623 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529624 alternative_service_vector[0].protocol);
9625 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9626 EXPECT_EQ(443, alternative_service_vector[0].port);
9627}
9628
bnc4f575852015-10-14 18:35:089629TEST_P(HttpNetworkTransactionTest, ClearAlternativeServices) {
9630 session_deps_.next_protos = SpdyNextProtos();
9631 session_deps_.use_alternative_services = true;
9632
9633 // Set an alternative service for origin.
9634 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9635 HttpServerProperties& http_server_properties =
9636 *session->http_server_properties();
9637 HostPortPair http_host_port_pair("www.example.org", 80);
9638 AlternativeService alternative_service(QUIC, "", 80);
9639 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9640 http_server_properties.SetAlternativeService(
9641 http_host_port_pair, alternative_service, 1.0, expiration);
9642 AlternativeServiceVector alternative_service_vector =
9643 http_server_properties.GetAlternativeServices(http_host_port_pair);
9644 EXPECT_EQ(1u, alternative_service_vector.size());
9645
9646 // Send a clear header.
9647 MockRead data_reads[] = {
9648 MockRead("HTTP/1.1 200 OK\r\n"),
9649 MockRead("Alt-Svc: clear\r\n"),
9650 MockRead("\r\n"),
9651 MockRead("hello world"),
9652 MockRead(SYNCHRONOUS, OK),
9653 };
9654 StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
9655 session_deps_.socket_factory->AddSocketDataProvider(&data);
9656
9657 HttpRequestInfo request;
9658 request.method = "GET";
9659 request.url = GURL("http://www.example.org/");
9660 request.load_flags = 0;
9661
9662 TestCompletionCallback callback;
9663
9664 scoped_ptr<HttpTransaction> trans(
9665 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9666
9667 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9668 EXPECT_EQ(OK, callback.GetResult(rv));
9669
9670 const HttpResponseInfo* response = trans->GetResponseInfo();
9671 ASSERT_TRUE(response != nullptr);
9672 ASSERT_TRUE(response->headers.get() != nullptr);
9673 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9674 EXPECT_FALSE(response->was_fetched_via_spdy);
9675 EXPECT_FALSE(response->was_npn_negotiated);
9676
9677 std::string response_data;
9678 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9679 EXPECT_EQ("hello world", response_data);
9680
9681 alternative_service_vector =
9682 http_server_properties.GetAlternativeServices(http_host_port_pair);
9683 EXPECT_TRUE(alternative_service_vector.empty());
9684}
9685
bnc54ec34b72015-08-26 19:34:569686// Alternative Service headers must be ignored when |use_alternative_services|
9687// is false.
9688TEST_P(HttpNetworkTransactionTest, DoNotHonorAlternativeServiceHeader) {
9689 session_deps_.next_protos = SpdyNextProtos();
9690 session_deps_.use_alternative_services = false;
9691
9692 std::string alternative_service_http_header =
9693 GetAlternativeServiceHttpHeader();
9694
9695 MockRead data_reads[] = {
9696 MockRead("HTTP/1.1 200 OK\r\n"),
9697 MockRead(alternative_service_http_header.c_str()),
9698 MockRead("\r\n"),
9699 MockRead("hello world"),
9700 MockRead(SYNCHRONOUS, OK),
9701 };
9702
9703 HttpRequestInfo request;
9704 request.method = "GET";
9705 request.url = GURL("http://www.example.org/");
9706 request.load_flags = 0;
9707
9708 StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
9709
9710 session_deps_.socket_factory->AddSocketDataProvider(&data);
9711
9712 TestCompletionCallback callback;
9713
mmenkee65e7af2015-10-13 17:16:429714 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc54ec34b72015-08-26 19:34:569715 scoped_ptr<HttpTransaction> trans(
9716 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9717
9718 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9719 EXPECT_EQ(ERR_IO_PENDING, rv);
9720
9721 HostPortPair http_host_port_pair("www.example.org", 80);
9722 HttpServerProperties& http_server_properties =
9723 *session->http_server_properties();
9724 AlternativeServiceVector alternative_service_vector =
9725 http_server_properties.GetAlternativeServices(http_host_port_pair);
9726 EXPECT_TRUE(alternative_service_vector.empty());
9727
9728 EXPECT_EQ(OK, callback.WaitForResult());
9729
9730 const HttpResponseInfo* response = trans->GetResponseInfo();
9731 ASSERT_TRUE(response != nullptr);
9732 ASSERT_TRUE(response->headers.get() != nullptr);
9733 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9734 EXPECT_FALSE(response->was_fetched_via_spdy);
9735 EXPECT_FALSE(response->was_npn_negotiated);
9736
9737 std::string response_data;
9738 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9739 EXPECT_EQ("hello world", response_data);
9740
9741 alternative_service_vector =
9742 http_server_properties.GetAlternativeServices(http_host_port_pair);
9743 EXPECT_TRUE(alternative_service_vector.empty());
9744}
9745
bncc958faa2015-07-31 18:14:529746TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) {
9747 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359748 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529749
9750 MockRead data_reads[] = {
9751 MockRead("HTTP/1.1 200 OK\r\n"),
9752 MockRead("Alt-Svc: "),
9753 MockRead(GetAlternateProtocolFromParam()),
bnc44858c82015-10-16 11:57:219754 MockRead("=\"www.example.com:443\";p=\"1.0\","),
bncc958faa2015-07-31 18:14:529755 MockRead("quic=\":1234\"\r\n\r\n"),
9756 MockRead("hello world"),
9757 MockRead(SYNCHRONOUS, OK),
9758 };
9759
9760 HttpRequestInfo request;
9761 request.method = "GET";
9762 request.url = GURL("http://www.example.org/");
9763 request.load_flags = 0;
9764
9765 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9766
9767 session_deps_.socket_factory->AddSocketDataProvider(&data);
9768
9769 TestCompletionCallback callback;
9770
mmenkee65e7af2015-10-13 17:16:429771 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529772 scoped_ptr<HttpTransaction> trans(
9773 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9774
9775 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9776 EXPECT_EQ(ERR_IO_PENDING, rv);
9777
9778 HostPortPair http_host_port_pair("www.example.org", 80);
9779 HttpServerProperties& http_server_properties =
9780 *session->http_server_properties();
9781 AlternativeServiceVector alternative_service_vector =
9782 http_server_properties.GetAlternativeServices(http_host_port_pair);
9783 EXPECT_TRUE(alternative_service_vector.empty());
9784
9785 EXPECT_EQ(OK, callback.WaitForResult());
9786
9787 const HttpResponseInfo* response = trans->GetResponseInfo();
9788 ASSERT_TRUE(response != NULL);
9789 ASSERT_TRUE(response->headers.get() != NULL);
9790 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9791 EXPECT_FALSE(response->was_fetched_via_spdy);
9792 EXPECT_FALSE(response->was_npn_negotiated);
9793
9794 std::string response_data;
9795 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9796 EXPECT_EQ("hello world", response_data);
9797
9798 alternative_service_vector =
9799 http_server_properties.GetAlternativeServices(http_host_port_pair);
9800 ASSERT_EQ(2u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389801 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529802 alternative_service_vector[0].protocol);
9803 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9804 EXPECT_EQ(443, alternative_service_vector[0].port);
9805 EXPECT_EQ(QUIC, alternative_service_vector[1].protocol);
9806 EXPECT_EQ("www.example.org", alternative_service_vector[1].host);
9807 EXPECT_EQ(1234, alternative_service_vector[1].port);
9808}
9809
bnc54ec34b72015-08-26 19:34:569810// Alternate Protocol headers must be honored even if |use_alternative_services|
9811// is false.
[email protected]23e482282013-06-14 16:08:029812TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]d7599122014-05-24 03:37:239813 session_deps_.next_protos = SpdyNextProtos();
bnc54ec34b72015-08-26 19:34:569814 session_deps_.use_alternative_services = false;
[email protected]a2cb8122010-03-10 17:22:429815
[email protected]8a0fc822013-06-27 20:52:439816 std::string alternate_protocol_http_header =
9817 GetAlternateProtocolHttpHeader();
9818
[email protected]564b4912010-03-09 16:30:429819 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:529820 MockRead("HTTP/1.1 200 OK\r\n"),
9821 MockRead(alternate_protocol_http_header.c_str()),
9822 MockRead("\r\n"),
9823 MockRead("hello world"),
9824 MockRead(SYNCHRONOUS, OK),
[email protected]564b4912010-03-09 16:30:429825 };
9826
9827 HttpRequestInfo request;
9828 request.method = "GET";
bncce36dca22015-04-21 22:11:239829 request.url = GURL("http://www.example.org/");
[email protected]564b4912010-03-09 16:30:429830 request.load_flags = 0;
9831
9832 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9833
[email protected]bb88e1d32013-05-03 23:11:079834 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]564b4912010-03-09 16:30:429835
[email protected]49639fa2011-12-20 23:22:419836 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:429837
mmenkee65e7af2015-10-13 17:16:429838 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:369839 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509840 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]564b4912010-03-09 16:30:429841
[email protected]49639fa2011-12-20 23:22:419842 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:429843 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:539844
bncce36dca22015-04-21 22:11:239845 HostPortPair http_host_port_pair("www.example.org", 80);
[email protected]9801e3702014-03-07 09:33:559846 HttpServerProperties& http_server_properties =
[email protected]17291a022011-10-10 07:32:539847 *session->http_server_properties();
bncd9b132e2015-07-08 05:16:109848 AlternativeServiceVector alternative_service_vector =
9849 http_server_properties.GetAlternativeServices(http_host_port_pair);
9850 EXPECT_TRUE(alternative_service_vector.empty());
[email protected]564b4912010-03-09 16:30:429851
9852 EXPECT_EQ(OK, callback.WaitForResult());
9853
9854 const HttpResponseInfo* response = trans->GetResponseInfo();
9855 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:509856 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]564b4912010-03-09 16:30:429857 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:539858 EXPECT_FALSE(response->was_fetched_via_spdy);
9859 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:429860
9861 std::string response_data;
9862 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9863 EXPECT_EQ("hello world", response_data);
9864
bncd9b132e2015-07-08 05:16:109865 alternative_service_vector =
9866 http_server_properties.GetAlternativeServices(http_host_port_pair);
9867 ASSERT_EQ(1u, alternative_service_vector.size());
9868 EXPECT_EQ(443, alternative_service_vector[0].port);
rdsmithebb50aa2015-11-12 03:44:389869 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncd9b132e2015-07-08 05:16:109870 alternative_service_vector[0].protocol);
[email protected]564b4912010-03-09 16:30:429871}
9872
rch89c6e102015-03-18 18:56:529873TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
9874 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359875 session_deps_.use_alternative_services = true;
rch89c6e102015-03-18 18:56:529876
9877 MockRead data_reads[] = {
9878 MockRead("HTTP/1.1 200 OK\r\n"),
9879 MockRead("Alternate-Protocol: \r\n\r\n"),
9880 MockRead("hello world"),
9881 MockRead(SYNCHRONOUS, OK),
9882 };
9883
9884 HttpRequestInfo request;
9885 request.method = "GET";
bncce36dca22015-04-21 22:11:239886 request.url = GURL("http://www.example.org/");
rch89c6e102015-03-18 18:56:529887 request.load_flags = 0;
9888
9889 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9890
9891 session_deps_.socket_factory->AddSocketDataProvider(&data);
9892
9893 TestCompletionCallback callback;
9894
mmenkee65e7af2015-10-13 17:16:429895 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rch89c6e102015-03-18 18:56:529896
bncce36dca22015-04-21 22:11:239897 HostPortPair http_host_port_pair("www.example.org", 80);
rch89c6e102015-03-18 18:56:529898 HttpServerProperties& http_server_properties =
9899 *session->http_server_properties();
bnccacc0992015-03-20 20:22:229900 AlternativeService alternative_service(QUIC, "", 80);
bnc7dc7e1b42015-07-28 14:43:129901 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9902 http_server_properties.SetAlternativeService(
9903 http_host_port_pair, alternative_service, 1.0, expiration);
bnccacc0992015-03-20 20:22:229904
bncd9b132e2015-07-08 05:16:109905 AlternativeServiceVector alternative_service_vector =
9906 http_server_properties.GetAlternativeServices(http_host_port_pair);
9907 ASSERT_EQ(1u, alternative_service_vector.size());
9908 EXPECT_EQ(QUIC, alternative_service_vector[0].protocol);
rch89c6e102015-03-18 18:56:529909
9910 scoped_ptr<HttpTransaction> trans(
9911 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9912
9913 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9914 EXPECT_EQ(ERR_IO_PENDING, rv);
9915
9916 EXPECT_EQ(OK, callback.WaitForResult());
9917
9918 const HttpResponseInfo* response = trans->GetResponseInfo();
9919 ASSERT_TRUE(response != NULL);
9920 ASSERT_TRUE(response->headers.get() != NULL);
9921 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9922 EXPECT_FALSE(response->was_fetched_via_spdy);
9923 EXPECT_FALSE(response->was_npn_negotiated);
9924
9925 std::string response_data;
9926 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9927 EXPECT_EQ("hello world", response_data);
9928
bncd9b132e2015-07-08 05:16:109929 alternative_service_vector =
9930 http_server_properties.GetAlternativeServices(http_host_port_pair);
9931 EXPECT_TRUE(alternative_service_vector.empty());
rch89c6e102015-03-18 18:56:529932}
9933
bncc958faa2015-07-31 18:14:529934TEST_P(HttpNetworkTransactionTest, AltSvcOverwritesAlternateProtocol) {
9935 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359936 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529937
9938 std::string alternative_service_http_header =
9939 GetAlternativeServiceHttpHeader();
9940 std::string alternate_protocol_http_header = GetAlternateProtocolHttpHeader();
9941
9942 MockRead data_reads[] = {
9943 MockRead("HTTP/1.1 200 OK\r\n"),
9944 MockRead(alternative_service_http_header.c_str()),
9945 MockRead(alternate_protocol_http_header.c_str()),
9946 MockRead("\r\n"),
9947 MockRead("hello world"),
9948 MockRead(SYNCHRONOUS, OK),
9949 };
9950
9951 HttpRequestInfo request;
9952 request.method = "GET";
9953 request.url = GURL("http://www.example.org/");
9954 request.load_flags = 0;
9955
9956 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9957
9958 session_deps_.socket_factory->AddSocketDataProvider(&data);
9959
9960 TestCompletionCallback callback;
9961
mmenkee65e7af2015-10-13 17:16:429962 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529963 scoped_ptr<HttpTransaction> trans(
9964 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9965
9966 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9967 EXPECT_EQ(ERR_IO_PENDING, rv);
9968
9969 HostPortPair http_host_port_pair("www.example.org", 80);
9970 HttpServerProperties& http_server_properties =
9971 *session->http_server_properties();
9972 AlternativeServiceVector alternative_service_vector =
9973 http_server_properties.GetAlternativeServices(http_host_port_pair);
9974 EXPECT_TRUE(alternative_service_vector.empty());
9975
9976 EXPECT_EQ(OK, callback.WaitForResult());
9977
9978 const HttpResponseInfo* response = trans->GetResponseInfo();
9979 ASSERT_TRUE(response != NULL);
9980 ASSERT_TRUE(response->headers.get() != NULL);
9981 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9982 EXPECT_FALSE(response->was_fetched_via_spdy);
9983 EXPECT_FALSE(response->was_npn_negotiated);
9984
9985 std::string response_data;
9986 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9987 EXPECT_EQ("hello world", response_data);
9988
9989 alternative_service_vector =
9990 http_server_properties.GetAlternativeServices(http_host_port_pair);
9991 ASSERT_EQ(1u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389992 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529993 alternative_service_vector[0].protocol);
9994 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9995 EXPECT_EQ(443, alternative_service_vector[0].port);
9996}
9997
bnc54ec34b72015-08-26 19:34:569998// When |use_alternative_services| is false, do not observe alternative service
9999// entries that point to a different host.
10000TEST_P(HttpNetworkTransactionTest, DisableAlternativeServiceToDifferentHost) {
10001 session_deps_.use_alternative_services = false;
10002
10003 HttpRequestInfo request;
10004 request.method = "GET";
10005 request.url = GURL("http://www.example.org/");
10006 request.load_flags = 0;
10007
10008 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
10009 StaticSocketDataProvider first_data;
10010 first_data.set_connect_data(mock_connect);
10011 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
10012
10013 MockRead data_reads[] = {
10014 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
10015 MockRead(ASYNC, OK),
10016 };
10017 StaticSocketDataProvider second_data(data_reads, arraysize(data_reads),
10018 nullptr, 0);
10019 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
10020
mmenkee65e7af2015-10-13 17:16:4210021 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc54ec34b72015-08-26 19:34:5610022
10023 base::WeakPtr<HttpServerProperties> http_server_properties =
10024 session->http_server_properties();
10025 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810026 AlternateProtocolFromNextProto(GetProtocol()), "different.example.org",
10027 80);
bnc54ec34b72015-08-26 19:34:5610028 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10029 http_server_properties->SetAlternativeService(
10030 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
10031
10032 scoped_ptr<HttpTransaction> trans(
10033 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10034 TestCompletionCallback callback;
10035
10036 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10037 // The connetion to origin was refused, and the alternative service should not
10038 // be used (even though mock data are there), therefore the request should
10039 // fail.
10040 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.GetResult(rv));
10041}
10042
zhongyi48704c182015-12-07 07:52:0210043TEST_P(HttpNetworkTransactionTest, IdentifyQuicBroken) {
10044 HostPortPair origin("origin.example.org", 443);
10045 HostPortPair alternative("alternative.example.org", 443);
10046 std::string origin_url = "https://origin.example.org:443";
10047 std::string alternative_url = "https://alternative.example.org:443";
10048
10049 // Negotiate HTTP/1.1 with alternative.example.org.
10050 SSLSocketDataProvider ssl(ASYNC, OK);
10051 ssl.SetNextProto(kProtoHTTP11);
10052 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10053
10054 // HTTP/1.1 data for request.
10055 MockWrite http_writes[] = {
10056 MockWrite("GET / HTTP/1.1\r\n"
10057 "Host: alternative.example.org\r\n"
10058 "Connection: keep-alive\r\n\r\n"),
10059 };
10060
10061 MockRead http_reads[] = {
10062 MockRead("HTTP/1.1 200 OK\r\n"
10063 "Content-Type: text/html; charset=iso-8859-1\r\n"
10064 "Content-Length: 40\r\n\r\n"
10065 "first HTTP/1.1 response from alternative"),
10066 };
10067 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
10068 http_writes, arraysize(http_writes));
10069 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
10070
10071 StaticSocketDataProvider data_refused;
10072 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
10073 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
10074
10075 // Set up a QUIC alternative service for origin.
10076 session_deps_.use_alternative_services = true;
10077 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10078 base::WeakPtr<HttpServerProperties> http_server_properties =
10079 session->http_server_properties();
10080 AlternativeService alternative_service(QUIC, alternative);
10081 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10082 http_server_properties->SetAlternativeService(origin, alternative_service,
10083 1.0, expiration);
10084 // Mark the QUIC alternative service as broken.
10085 http_server_properties->MarkAlternativeServiceBroken(alternative_service);
10086
10087 scoped_ptr<HttpTransaction> trans(
10088 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10089 HttpRequestInfo request;
10090 request.method = "GET";
10091 request.url = GURL(origin_url);
10092 request.load_flags = 0;
10093 TestCompletionCallback callback;
10094 NetErrorDetails details;
10095 EXPECT_FALSE(details.quic_broken);
10096
10097 trans->Start(&request, callback.callback(), BoundNetLog());
10098 trans->PopulateNetErrorDetails(&details);
10099 EXPECT_TRUE(details.quic_broken);
10100}
10101
10102TEST_P(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
10103 HostPortPair origin("origin.example.org", 443);
10104 HostPortPair alternative1("alternative1.example.org", 443);
10105 HostPortPair alternative2("alternative2.example.org", 443);
10106 std::string origin_url = "https://origin.example.org:443";
10107 std::string alternative_url1 = "https://alternative1.example.org:443";
10108 std::string alternative_url2 = "https://alternative2.example.org:443";
10109
10110 // Negotiate HTTP/1.1 with alternative1.example.org.
10111 SSLSocketDataProvider ssl(ASYNC, OK);
10112 ssl.SetNextProto(kProtoHTTP11);
10113 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10114
10115 // HTTP/1.1 data for request.
10116 MockWrite http_writes[] = {
10117 MockWrite("GET / HTTP/1.1\r\n"
10118 "Host: alternative1.example.org\r\n"
10119 "Connection: keep-alive\r\n\r\n"),
10120 };
10121
10122 MockRead http_reads[] = {
10123 MockRead("HTTP/1.1 200 OK\r\n"
10124 "Content-Type: text/html; charset=iso-8859-1\r\n"
10125 "Content-Length: 40\r\n\r\n"
10126 "first HTTP/1.1 response from alternative1"),
10127 };
10128 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
10129 http_writes, arraysize(http_writes));
10130 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
10131
10132 StaticSocketDataProvider data_refused;
10133 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
10134 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
10135
10136 session_deps_.use_alternative_services = true;
10137 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10138 base::WeakPtr<HttpServerProperties> http_server_properties =
10139 session->http_server_properties();
10140
10141 // Set up two QUIC alternative services for origin.
10142 AlternativeServiceInfoVector alternative_service_info_vector;
10143 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10144
10145 AlternativeService alternative_service1(QUIC, alternative1);
10146 AlternativeServiceInfo alternative_service_info1(alternative_service1, 1.0,
10147 expiration);
10148 alternative_service_info_vector.push_back(alternative_service_info1);
10149 AlternativeService alternative_service2(QUIC, alternative2);
10150 AlternativeServiceInfo alternative_service_info2(alternative_service2, 1.0,
10151 expiration);
10152 alternative_service_info_vector.push_back(alternative_service_info2);
10153
10154 http_server_properties->SetAlternativeServices(
10155 origin, alternative_service_info_vector);
10156
10157 // Mark one of the QUIC alternative service as broken.
10158 http_server_properties->MarkAlternativeServiceBroken(alternative_service1);
10159
10160 const AlternativeServiceVector alternative_service_vector =
10161 http_server_properties->GetAlternativeServices(origin);
10162
10163 scoped_ptr<HttpTransaction> trans(
10164 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10165 HttpRequestInfo request;
10166 request.method = "GET";
10167 request.url = GURL(origin_url);
10168 request.load_flags = 0;
10169 TestCompletionCallback callback;
10170 NetErrorDetails details;
10171 EXPECT_FALSE(details.quic_broken);
10172
10173 trans->Start(&request, callback.callback(), BoundNetLog());
10174 trans->PopulateNetErrorDetails(&details);
10175 EXPECT_FALSE(details.quic_broken);
10176}
10177
[email protected]23e482282013-06-14 16:08:0210178TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310179 MarkBrokenAlternateProtocolAndFallback) {
bnc55ff9da2015-08-19 18:42:3510180 session_deps_.use_alternative_services = true;
[email protected]564b4912010-03-09 16:30:4210181
10182 HttpRequestInfo request;
10183 request.method = "GET";
bncce36dca22015-04-21 22:11:2310184 request.url = GURL("http://www.example.org/");
[email protected]564b4912010-03-09 16:30:4210185 request.load_flags = 0;
10186
[email protected]d973e99a2012-02-17 21:02:3610187 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4210188 StaticSocketDataProvider first_data;
10189 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710190 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]564b4912010-03-09 16:30:4210191
10192 MockRead data_reads[] = {
10193 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10194 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610195 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4210196 };
10197 StaticSocketDataProvider second_data(
10198 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710199 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4210200
mmenkee65e7af2015-10-13 17:16:4210201 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4210202
[email protected]30d4c022013-07-18 22:58:1610203 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310204 session->http_server_properties();
bnc8445b3002015-03-13 01:57:0910205 const HostPortPair host_port_pair = HostPortPair::FromURL(request.url);
[email protected]3912662a32011-10-04 00:51:1110206 // Port must be < 1024, or the header will be ignored (since initial port was
10207 // port 80 (another restricted port).
bncd9b132e2015-07-08 05:16:1010208 const AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810209 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bncd9b132e2015-07-08 05:16:1010210 666); // Port is ignored by MockConnect anyway.
bnc7dc7e1b42015-07-28 14:43:1210211 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10212 http_server_properties->SetAlternativeService(
10213 host_port_pair, alternative_service, 1.0, expiration);
[email protected]564b4912010-03-09 16:30:4210214
[email protected]262eec82013-03-19 21:01:3610215 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010216 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110217 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4210218
[email protected]49639fa2011-12-20 23:22:4110219 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:4210220 EXPECT_EQ(ERR_IO_PENDING, rv);
10221 EXPECT_EQ(OK, callback.WaitForResult());
10222
10223 const HttpResponseInfo* response = trans->GetResponseInfo();
10224 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010225 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]564b4912010-03-09 16:30:4210226 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10227
10228 std::string response_data;
10229 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10230 EXPECT_EQ("hello world", response_data);
10231
bncd9b132e2015-07-08 05:16:1010232 const AlternativeServiceVector alternative_service_vector =
10233 http_server_properties->GetAlternativeServices(host_port_pair);
10234 ASSERT_EQ(1u, alternative_service_vector.size());
10235 EXPECT_EQ(alternative_service, alternative_service_vector[0]);
10236 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
10237 alternative_service_vector[0]));
[email protected]564b4912010-03-09 16:30:4210238}
10239
bnc55ff9da2015-08-19 18:42:3510240// Ensure that we are not allowed to redirect traffic via an alternate protocol
10241// to an unrestricted (port >= 1024) when the original traffic was on a
10242// restricted port (port < 1024). Ensure that we can redirect in all other
10243// cases.
[email protected]23e482282013-06-14 16:08:0210244TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310245 AlternateProtocolPortRestrictedBlocked) {
bnc55ff9da2015-08-19 18:42:3510246 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110247
10248 HttpRequestInfo restricted_port_request;
10249 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310250 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1110251 restricted_port_request.load_flags = 0;
10252
[email protected]d973e99a2012-02-17 21:02:3610253 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110254 StaticSocketDataProvider first_data;
10255 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710256 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110257
10258 MockRead data_reads[] = {
10259 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10260 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610261 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110262 };
10263 StaticSocketDataProvider second_data(
10264 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710265 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110266
mmenkee65e7af2015-10-13 17:16:4210267 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110268
[email protected]30d4c022013-07-18 22:58:1610269 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310270 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110271 const int kUnrestrictedAlternatePort = 1024;
bnccacc0992015-03-20 20:22:2210272 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810273 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210274 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210275 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210276 http_server_properties->SetAlternativeService(
10277 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210278 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110279
[email protected]262eec82013-03-19 21:01:3610280 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010281 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110282 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110283
[email protected]49639fa2011-12-20 23:22:4110284 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:3610285 &restricted_port_request,
10286 callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110287 EXPECT_EQ(ERR_IO_PENDING, rv);
10288 // Invalid change to unrestricted port should fail.
10289 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
[email protected]c54c6962013-02-01 04:53:1910290}
[email protected]3912662a32011-10-04 00:51:1110291
bnc55ff9da2015-08-19 18:42:3510292// Ensure that we are allowed to redirect traffic via an alternate protocol to
10293// an unrestricted (port >= 1024) when the original traffic was on a restricted
10294// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
[email protected]23e482282013-06-14 16:08:0210295TEST_P(HttpNetworkTransactionTest,
[email protected]c54c6962013-02-01 04:53:1910296 AlternateProtocolPortRestrictedPermitted) {
bnc55ff9da2015-08-19 18:42:3510297 session_deps_.use_alternative_services = true;
[email protected]bb88e1d32013-05-03 23:11:0710298 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1910299
10300 HttpRequestInfo restricted_port_request;
10301 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310302 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1910303 restricted_port_request.load_flags = 0;
10304
10305 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
10306 StaticSocketDataProvider first_data;
10307 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710308 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1910309
10310 MockRead data_reads[] = {
10311 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10312 MockRead("hello world"),
10313 MockRead(ASYNC, OK),
10314 };
10315 StaticSocketDataProvider second_data(
10316 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710317 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]c54c6962013-02-01 04:53:1910318
mmenkee65e7af2015-10-13 17:16:4210319 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1910320
[email protected]30d4c022013-07-18 22:58:1610321 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]c54c6962013-02-01 04:53:1910322 session->http_server_properties();
10323 const int kUnrestrictedAlternatePort = 1024;
bnccacc0992015-03-20 20:22:2210324 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810325 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210326 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210327 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210328 http_server_properties->SetAlternativeService(
10329 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210330 1.0, expiration);
[email protected]c54c6962013-02-01 04:53:1910331
[email protected]262eec82013-03-19 21:01:3610332 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010333 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]c54c6962013-02-01 04:53:1910334 TestCompletionCallback callback;
10335
10336 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
[email protected]262eec82013-03-19 21:01:3610337 &restricted_port_request,
10338 callback.callback(), BoundNetLog()));
[email protected]c54c6962013-02-01 04:53:1910339 // Change to unrestricted port should succeed.
10340 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110341}
10342
bnc55ff9da2015-08-19 18:42:3510343// Ensure that we are not allowed to redirect traffic via an alternate protocol
10344// to an unrestricted (port >= 1024) when the original traffic was on a
10345// restricted port (port < 1024). Ensure that we can redirect in all other
10346// cases.
[email protected]23e482282013-06-14 16:08:0210347TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310348 AlternateProtocolPortRestrictedAllowed) {
bnc55ff9da2015-08-19 18:42:3510349 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110350
10351 HttpRequestInfo restricted_port_request;
10352 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310353 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1110354 restricted_port_request.load_flags = 0;
10355
[email protected]d973e99a2012-02-17 21:02:3610356 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110357 StaticSocketDataProvider first_data;
10358 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710359 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110360
10361 MockRead data_reads[] = {
10362 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10363 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610364 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110365 };
10366 StaticSocketDataProvider second_data(
10367 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710368 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110369
mmenkee65e7af2015-10-13 17:16:4210370 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110371
[email protected]30d4c022013-07-18 22:58:1610372 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310373 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110374 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210375 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810376 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210377 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210378 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210379 http_server_properties->SetAlternativeService(
10380 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210381 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110382
[email protected]262eec82013-03-19 21:01:3610383 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010384 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110385 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110386
[email protected]49639fa2011-12-20 23:22:4110387 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:3610388 &restricted_port_request,
10389 callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110390 EXPECT_EQ(ERR_IO_PENDING, rv);
10391 // Valid change to restricted port should pass.
10392 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110393}
10394
bnc55ff9da2015-08-19 18:42:3510395// Ensure that we are not allowed to redirect traffic via an alternate protocol
10396// to an unrestricted (port >= 1024) when the original traffic was on a
10397// restricted port (port < 1024). Ensure that we can redirect in all other
10398// cases.
[email protected]23e482282013-06-14 16:08:0210399TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310400 AlternateProtocolPortUnrestrictedAllowed1) {
bnc55ff9da2015-08-19 18:42:3510401 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110402
10403 HttpRequestInfo unrestricted_port_request;
10404 unrestricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310405 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110406 unrestricted_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);
[email protected]3912662a32011-10-04 00:51:1110421
mmenkee65e7af2015-10-13 17:16:4210422 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110423
[email protected]30d4c022013-07-18 22:58:1610424 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310425 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110426 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210427 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810428 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210429 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210430 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210431 http_server_properties->SetAlternativeService(
10432 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210433 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110434
[email protected]262eec82013-03-19 21:01:3610435 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010436 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110437 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110438
[email protected]49639fa2011-12-20 23:22:4110439 int rv = trans->Start(
10440 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110441 EXPECT_EQ(ERR_IO_PENDING, rv);
10442 // Valid change to restricted port should pass.
10443 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110444}
10445
bnc55ff9da2015-08-19 18:42:3510446// Ensure that we are not allowed to redirect traffic via an alternate protocol
10447// to an unrestricted (port >= 1024) when the original traffic was on a
10448// restricted port (port < 1024). Ensure that we can redirect in all other
10449// cases.
[email protected]23e482282013-06-14 16:08:0210450TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310451 AlternateProtocolPortUnrestrictedAllowed2) {
bnc55ff9da2015-08-19 18:42:3510452 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110453
10454 HttpRequestInfo unrestricted_port_request;
10455 unrestricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310456 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110457 unrestricted_port_request.load_flags = 0;
10458
[email protected]d973e99a2012-02-17 21:02:3610459 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110460 StaticSocketDataProvider first_data;
10461 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710462 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110463
10464 MockRead data_reads[] = {
10465 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10466 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610467 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110468 };
10469 StaticSocketDataProvider second_data(
10470 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710471 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110472
mmenkee65e7af2015-10-13 17:16:4210473 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110474
[email protected]30d4c022013-07-18 22:58:1610475 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310476 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2210477 const int kUnrestrictedAlternatePort = 1025;
bnccacc0992015-03-20 20:22:2210478 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810479 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210480 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210481 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210482 http_server_properties->SetAlternativeService(
10483 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210484 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110485
[email protected]262eec82013-03-19 21:01:3610486 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010487 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110488 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110489
[email protected]49639fa2011-12-20 23:22:4110490 int rv = trans->Start(
10491 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110492 EXPECT_EQ(ERR_IO_PENDING, rv);
10493 // Valid change to an unrestricted port should pass.
10494 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110495}
10496
bnc55ff9da2015-08-19 18:42:3510497// Ensure that we are not allowed to redirect traffic via an alternate protocol
10498// to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
10499// once the alternate protocol request fails.
[email protected]d7599122014-05-24 03:37:2310500TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
bnc55ff9da2015-08-19 18:42:3510501 session_deps_.use_alternative_services = true;
[email protected]eb6234e2012-01-19 01:50:0210502
10503 HttpRequestInfo request;
10504 request.method = "GET";
bncce36dca22015-04-21 22:11:2310505 request.url = GURL("http://www.example.org/");
[email protected]eb6234e2012-01-19 01:50:0210506 request.load_flags = 0;
10507
10508 // The alternate protocol request will error out before we attempt to connect,
10509 // so only the standard HTTP request will try to connect.
10510 MockRead data_reads[] = {
10511 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10512 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610513 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0210514 };
10515 StaticSocketDataProvider data(
10516 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710517 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0210518
mmenkee65e7af2015-10-13 17:16:4210519 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0210520
[email protected]30d4c022013-07-18 22:58:1610521 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0210522 session->http_server_properties();
10523 const int kUnsafePort = 7;
bnccacc0992015-03-20 20:22:2210524 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810525 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210526 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1210527 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210528 http_server_properties->SetAlternativeService(
bnc7dc7e1b42015-07-28 14:43:1210529 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
[email protected]eb6234e2012-01-19 01:50:0210530
[email protected]262eec82013-03-19 21:01:3610531 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010532 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]eb6234e2012-01-19 01:50:0210533 TestCompletionCallback callback;
10534
10535 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10536 EXPECT_EQ(ERR_IO_PENDING, rv);
10537 // The HTTP request should succeed.
10538 EXPECT_EQ(OK, callback.WaitForResult());
10539
[email protected]eb6234e2012-01-19 01:50:0210540 const HttpResponseInfo* response = trans->GetResponseInfo();
10541 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010542 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]eb6234e2012-01-19 01:50:0210543 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10544
10545 std::string response_data;
10546 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10547 EXPECT_EQ("hello world", response_data);
10548}
10549
[email protected]23e482282013-06-14 16:08:0210550TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510551 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310552 session_deps_.next_protos = SpdyNextProtos();
[email protected]2ff8b312010-04-26 22:20:5410553
10554 HttpRequestInfo request;
10555 request.method = "GET";
bncce36dca22015-04-21 22:11:2310556 request.url = GURL("http://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5410557 request.load_flags = 0;
10558
[email protected]8a0fc822013-06-27 20:52:4310559 std::string alternate_protocol_http_header =
10560 GetAlternateProtocolHttpHeader();
10561
[email protected]2ff8b312010-04-26 22:20:5410562 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210563 MockRead("HTTP/1.1 200 OK\r\n"),
10564 MockRead(alternate_protocol_http_header.c_str()),
10565 MockRead("\r\n"),
10566 MockRead("hello world"),
10567 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10568 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5410569
10570 StaticSocketDataProvider first_transaction(
10571 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710572 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2ff8b312010-04-26 22:20:5410573
[email protected]8ddf8322012-02-23 18:08:0610574 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810575 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310576 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10577 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710578 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2ff8b312010-04-26 22:20:5410579
[email protected]cdf8f7e72013-05-23 10:56:4610580 scoped_ptr<SpdyFrame> req(
10581 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1310582 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]2ff8b312010-04-26 22:20:5410583
[email protected]23e482282013-06-14 16:08:0210584 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10585 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5410586 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310587 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5410588 };
10589
rch8e6c6c42015-05-01 14:05:1310590 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10591 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710592 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5410593
[email protected]d973e99a2012-02-17 21:02:3610594 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510595 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10596 NULL, 0, NULL, 0);
10597 hanging_non_alternate_protocol_socket.set_connect_data(
10598 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710599 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510600 &hanging_non_alternate_protocol_socket);
10601
[email protected]49639fa2011-12-20 23:22:4110602 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5410603
mmenkee65e7af2015-10-13 17:16:4210604 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610605 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010606 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410607
[email protected]49639fa2011-12-20 23:22:4110608 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410609 EXPECT_EQ(ERR_IO_PENDING, rv);
10610 EXPECT_EQ(OK, callback.WaitForResult());
10611
10612 const HttpResponseInfo* response = trans->GetResponseInfo();
10613 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010614 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5410615 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10616
10617 std::string response_data;
10618 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10619 EXPECT_EQ("hello world", response_data);
10620
[email protected]90499482013-06-01 00:39:5010621 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410622
[email protected]49639fa2011-12-20 23:22:4110623 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410624 EXPECT_EQ(ERR_IO_PENDING, rv);
10625 EXPECT_EQ(OK, callback.WaitForResult());
10626
10627 response = trans->GetResponseInfo();
10628 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010629 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210630 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310631 EXPECT_TRUE(response->was_fetched_via_spdy);
10632 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5410633
10634 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10635 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5410636}
10637
[email protected]23e482282013-06-14 16:08:0210638TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
bnc55ff9da2015-08-19 18:42:3510639 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310640 session_deps_.next_protos = SpdyNextProtos();
[email protected]2d6728692011-03-12 01:39:5510641
10642 HttpRequestInfo request;
10643 request.method = "GET";
bncce36dca22015-04-21 22:11:2310644 request.url = GURL("http://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510645 request.load_flags = 0;
10646
[email protected]8a0fc822013-06-27 20:52:4310647 std::string alternate_protocol_http_header =
10648 GetAlternateProtocolHttpHeader();
10649
[email protected]2d6728692011-03-12 01:39:5510650 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210651 MockRead("HTTP/1.1 200 OK\r\n"),
10652 MockRead(alternate_protocol_http_header.c_str()),
10653 MockRead("\r\n"),
10654 MockRead("hello world"),
10655 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10656 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510657 };
10658
10659 StaticSocketDataProvider first_transaction(
10660 data_reads, arraysize(data_reads), NULL, 0);
10661 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
[email protected]bb88e1d32013-05-03 23:11:0710662 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510663
[email protected]d973e99a2012-02-17 21:02:3610664 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
mmenkecc2298e2015-12-07 18:20:1810665 StaticSocketDataProvider hanging_socket1(NULL, 0, NULL, 0);
10666 hanging_socket1.set_connect_data(never_finishing_connect);
[email protected]2d6728692011-03-12 01:39:5510667 // Socket 2 and 3 are the hanging Alternate-Protocol and
10668 // non-Alternate-Protocol jobs from the 2nd transaction.
mmenkecc2298e2015-12-07 18:20:1810669 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
10670
10671 StaticSocketDataProvider hanging_socket2(NULL, 0, NULL, 0);
10672 hanging_socket2.set_connect_data(never_finishing_connect);
10673 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5510674
[email protected]8ddf8322012-02-23 18:08:0610675 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810676 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310677 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10678 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710679 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510680
[email protected]cdf8f7e72013-05-23 10:56:4610681 scoped_ptr<SpdyFrame> req1(
10682 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10683 scoped_ptr<SpdyFrame> req2(
10684 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]2d6728692011-03-12 01:39:5510685 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1310686 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
[email protected]2d6728692011-03-12 01:39:5510687 };
[email protected]23e482282013-06-14 16:08:0210688 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10689 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
10690 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10691 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5510692 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310693 CreateMockRead(*resp1, 2),
10694 CreateMockRead(*data1, 3),
10695 CreateMockRead(*resp2, 4),
10696 CreateMockRead(*data2, 5),
10697 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5510698 };
10699
rch8e6c6c42015-05-01 14:05:1310700 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10701 arraysize(spdy_writes));
[email protected]2d6728692011-03-12 01:39:5510702 // Socket 4 is the successful Alternate-Protocol for transaction 3.
[email protected]bb88e1d32013-05-03 23:11:0710703 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5510704
10705 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
mmenkecc2298e2015-12-07 18:20:1810706 StaticSocketDataProvider hanging_socket3(NULL, 0, NULL, 0);
10707 hanging_socket3.set_connect_data(never_finishing_connect);
10708 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5510709
mmenkee65e7af2015-10-13 17:16:4210710 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4110711 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5010712 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5510713
[email protected]49639fa2011-12-20 23:22:4110714 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510715 EXPECT_EQ(ERR_IO_PENDING, rv);
10716 EXPECT_EQ(OK, callback1.WaitForResult());
10717
10718 const HttpResponseInfo* response = trans1.GetResponseInfo();
10719 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010720 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510721 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10722
10723 std::string response_data;
10724 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10725 EXPECT_EQ("hello world", response_data);
10726
[email protected]49639fa2011-12-20 23:22:4110727 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5010728 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110729 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510730 EXPECT_EQ(ERR_IO_PENDING, rv);
10731
[email protected]49639fa2011-12-20 23:22:4110732 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5010733 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110734 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510735 EXPECT_EQ(ERR_IO_PENDING, rv);
10736
10737 EXPECT_EQ(OK, callback2.WaitForResult());
10738 EXPECT_EQ(OK, callback3.WaitForResult());
10739
10740 response = trans2.GetResponseInfo();
10741 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010742 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210743 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5510744 EXPECT_TRUE(response->was_fetched_via_spdy);
10745 EXPECT_TRUE(response->was_npn_negotiated);
10746 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10747 EXPECT_EQ("hello!", response_data);
10748
10749 response = trans3.GetResponseInfo();
10750 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010751 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210752 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5510753 EXPECT_TRUE(response->was_fetched_via_spdy);
10754 EXPECT_TRUE(response->was_npn_negotiated);
10755 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
10756 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5510757}
10758
[email protected]23e482282013-06-14 16:08:0210759TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510760 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310761 session_deps_.next_protos = SpdyNextProtos();
[email protected]2d6728692011-03-12 01:39:5510762
10763 HttpRequestInfo request;
10764 request.method = "GET";
bncce36dca22015-04-21 22:11:2310765 request.url = GURL("http://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510766 request.load_flags = 0;
10767
[email protected]8a0fc822013-06-27 20:52:4310768 std::string alternate_protocol_http_header =
10769 GetAlternateProtocolHttpHeader();
10770
[email protected]2d6728692011-03-12 01:39:5510771 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210772 MockRead("HTTP/1.1 200 OK\r\n"),
10773 MockRead(alternate_protocol_http_header.c_str()),
10774 MockRead("\r\n"),
10775 MockRead("hello world"),
10776 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10777 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510778 };
10779
10780 StaticSocketDataProvider first_transaction(
10781 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710782 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510783
[email protected]8ddf8322012-02-23 18:08:0610784 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810785 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0710786 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510787
[email protected]d973e99a2012-02-17 21:02:3610788 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510789 StaticSocketDataProvider hanging_alternate_protocol_socket(
10790 NULL, 0, NULL, 0);
10791 hanging_alternate_protocol_socket.set_connect_data(
10792 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710793 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510794 &hanging_alternate_protocol_socket);
10795
10796 // 2nd request is just a copy of the first one, over HTTP again.
mmenkecc2298e2015-12-07 18:20:1810797 StaticSocketDataProvider second_transaction(data_reads, arraysize(data_reads),
10798 NULL, 0);
10799 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
[email protected]2d6728692011-03-12 01:39:5510800
[email protected]49639fa2011-12-20 23:22:4110801 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5510802
mmenkee65e7af2015-10-13 17:16:4210803 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610804 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010805 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510806
[email protected]49639fa2011-12-20 23:22:4110807 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510808 EXPECT_EQ(ERR_IO_PENDING, rv);
10809 EXPECT_EQ(OK, callback.WaitForResult());
10810
10811 const HttpResponseInfo* response = trans->GetResponseInfo();
10812 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010813 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510814 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10815
10816 std::string response_data;
10817 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10818 EXPECT_EQ("hello world", response_data);
10819
[email protected]90499482013-06-01 00:39:5010820 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510821
[email protected]49639fa2011-12-20 23:22:4110822 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510823 EXPECT_EQ(ERR_IO_PENDING, rv);
10824 EXPECT_EQ(OK, callback.WaitForResult());
10825
10826 response = trans->GetResponseInfo();
10827 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010828 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510829 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10830 EXPECT_FALSE(response->was_fetched_via_spdy);
10831 EXPECT_FALSE(response->was_npn_negotiated);
10832
10833 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10834 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5510835}
10836
[email protected]631f1322010-04-30 17:59:1110837class CapturingProxyResolver : public ProxyResolver {
10838 public:
sammce90c9212015-05-27 23:43:3510839 CapturingProxyResolver() {}
dchengb03027d2014-10-21 12:00:2010840 ~CapturingProxyResolver() override {}
[email protected]631f1322010-04-30 17:59:1110841
dchengb03027d2014-10-21 12:00:2010842 int GetProxyForURL(const GURL& url,
10843 ProxyInfo* results,
10844 const CompletionCallback& callback,
10845 RequestHandle* request,
10846 const BoundNetLog& net_log) override {
[email protected]fae7669f2010-08-02 21:49:4010847 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
10848 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:4210849 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:1110850 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:4210851 return OK;
[email protected]631f1322010-04-30 17:59:1110852 }
10853
dchengb03027d2014-10-21 12:00:2010854 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
[email protected]631f1322010-04-30 17:59:1110855
dchengb03027d2014-10-21 12:00:2010856 LoadState GetLoadState(RequestHandle request) const override {
[email protected]f2c971f2011-11-08 00:33:1710857 NOTREACHED();
10858 return LOAD_STATE_IDLE;
10859 }
10860
[email protected]24476402010-07-20 20:55:1710861 const std::vector<GURL>& resolved() const { return resolved_; }
10862
10863 private:
[email protected]631f1322010-04-30 17:59:1110864 std::vector<GURL> resolved_;
10865
10866 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
10867};
10868
sammce64b2362015-04-29 03:50:2310869class CapturingProxyResolverFactory : public ProxyResolverFactory {
10870 public:
10871 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
10872 : ProxyResolverFactory(false), resolver_(resolver) {}
10873
10874 int CreateProxyResolver(
10875 const scoped_refptr<ProxyResolverScriptData>& pac_script,
10876 scoped_ptr<ProxyResolver>* resolver,
10877 const net::CompletionCallback& callback,
10878 scoped_ptr<Request>* request) override {
10879 resolver->reset(new ForwardingProxyResolver(resolver_));
10880 return OK;
10881 }
10882
10883 private:
10884 ProxyResolver* resolver_;
10885};
10886
[email protected]23e482282013-06-14 16:08:0210887TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310888 UseAlternateProtocolForTunneledNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510889 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310890 session_deps_.next_protos = SpdyNextProtos();
[email protected]631f1322010-04-30 17:59:1110891
10892 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4210893 proxy_config.set_auto_detect(true);
10894 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1110895
sammc5dd160c2015-04-02 02:43:1310896 CapturingProxyResolver capturing_proxy_resolver;
[email protected]bb88e1d32013-05-03 23:11:0710897 session_deps_.proxy_service.reset(new ProxyService(
csharrisonb7e3a082015-09-22 19:13:0410898 make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)),
sammc5dd160c2015-04-02 02:43:1310899 make_scoped_ptr(
sammce64b2362015-04-29 03:50:2310900 new CapturingProxyResolverFactory(&capturing_proxy_resolver)),
[email protected]66761b952010-06-25 21:30:3810901 NULL));
vishal.b62985ca92015-04-17 08:45:5110902 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710903 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1110904
10905 HttpRequestInfo request;
10906 request.method = "GET";
bncce36dca22015-04-21 22:11:2310907 request.url = GURL("http://www.example.org/");
[email protected]631f1322010-04-30 17:59:1110908 request.load_flags = 0;
10909
[email protected]8a0fc822013-06-27 20:52:4310910 std::string alternate_protocol_http_header =
10911 GetAlternateProtocolHttpHeader();
10912
[email protected]631f1322010-04-30 17:59:1110913 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210914 MockRead("HTTP/1.1 200 OK\r\n"),
10915 MockRead(alternate_protocol_http_header.c_str()),
10916 MockRead("\r\n"),
10917 MockRead("hello world"),
10918 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10919 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1110920 };
10921
10922 StaticSocketDataProvider first_transaction(
10923 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710924 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]631f1322010-04-30 17:59:1110925
[email protected]8ddf8322012-02-23 18:08:0610926 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810927 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310928 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10929 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710930 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]631f1322010-04-30 17:59:1110931
[email protected]cdf8f7e72013-05-23 10:56:4610932 scoped_ptr<SpdyFrame> req(
10933 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]631f1322010-04-30 17:59:1110934 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1310935 MockWrite(ASYNC, 0,
10936 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1710937 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1310938 "Proxy-Connection: keep-alive\r\n\r\n"),
10939 CreateMockWrite(*req, 2),
[email protected]631f1322010-04-30 17:59:1110940 };
10941
[email protected]d911f1b2010-05-05 22:39:4210942 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10943
[email protected]23e482282013-06-14 16:08:0210944 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10945 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:1110946 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310947 MockRead(ASYNC, 1, kCONNECTResponse),
10948 CreateMockRead(*resp.get(), 3),
10949 CreateMockRead(*data.get(), 4),
10950 MockRead(ASYNC, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1110951 };
10952
rch8e6c6c42015-05-01 14:05:1310953 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10954 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710955 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1110956
[email protected]d973e99a2012-02-17 21:02:3610957 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510958 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10959 NULL, 0, NULL, 0);
10960 hanging_non_alternate_protocol_socket.set_connect_data(
10961 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710962 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510963 &hanging_non_alternate_protocol_socket);
10964
[email protected]49639fa2011-12-20 23:22:4110965 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1110966
mmenkee65e7af2015-10-13 17:16:4210967 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610968 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010969 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1110970
[email protected]49639fa2011-12-20 23:22:4110971 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:1110972 EXPECT_EQ(ERR_IO_PENDING, rv);
10973 EXPECT_EQ(OK, callback.WaitForResult());
10974
10975 const HttpResponseInfo* response = trans->GetResponseInfo();
10976 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010977 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]631f1322010-04-30 17:59:1110978 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310979 EXPECT_FALSE(response->was_fetched_via_spdy);
10980 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:1110981
10982 std::string response_data;
10983 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10984 EXPECT_EQ("hello world", response_data);
10985
[email protected]90499482013-06-01 00:39:5010986 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1110987
[email protected]49639fa2011-12-20 23:22:4110988 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:1110989 EXPECT_EQ(ERR_IO_PENDING, rv);
10990 EXPECT_EQ(OK, callback.WaitForResult());
10991
10992 response = trans->GetResponseInfo();
10993 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010994 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210995 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310996 EXPECT_TRUE(response->was_fetched_via_spdy);
10997 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:1110998
10999 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11000 EXPECT_EQ("hello!", response_data);
sammc5dd160c2015-04-02 02:43:1311001 ASSERT_EQ(3u, capturing_proxy_resolver.resolved().size());
bncce36dca22015-04-21 22:11:2311002 EXPECT_EQ("http://www.example.org/",
sammc5dd160c2015-04-02 02:43:1311003 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2311004 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1311005 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1111006
[email protected]029c83b62013-01-24 05:28:2011007 LoadTimingInfo load_timing_info;
11008 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11009 TestLoadTimingNotReusedWithPac(load_timing_info,
11010 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1111011}
[email protected]631f1322010-04-30 17:59:1111012
[email protected]23e482282013-06-14 16:08:0211013TEST_P(HttpNetworkTransactionTest,
[email protected]2ff8b312010-04-26 22:20:5411014 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
bnc55ff9da2015-08-19 18:42:3511015 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311016 session_deps_.next_protos = SpdyNextProtos();
[email protected]2ff8b312010-04-26 22:20:5411017
11018 HttpRequestInfo request;
11019 request.method = "GET";
bncce36dca22015-04-21 22:11:2311020 request.url = GURL("http://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5411021 request.load_flags = 0;
11022
[email protected]8a0fc822013-06-27 20:52:4311023 std::string alternate_protocol_http_header =
11024 GetAlternateProtocolHttpHeader();
11025
[email protected]2ff8b312010-04-26 22:20:5411026 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211027 MockRead("HTTP/1.1 200 OK\r\n"),
11028 MockRead(alternate_protocol_http_header.c_str()),
11029 MockRead("\r\n"),
11030 MockRead("hello world"),
11031 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5411032 };
11033
11034 StaticSocketDataProvider first_transaction(
11035 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0711036 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2ff8b312010-04-26 22:20:5411037
[email protected]8ddf8322012-02-23 18:08:0611038 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811039 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2311040 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11041 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0711042 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2ff8b312010-04-26 22:20:5411043
[email protected]cdf8f7e72013-05-23 10:56:4611044 scoped_ptr<SpdyFrame> req(
11045 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1311046 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]2ff8b312010-04-26 22:20:5411047
[email protected]23e482282013-06-14 16:08:0211048 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11049 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5411050 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1311051 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5411052 };
11053
rch8e6c6c42015-05-01 14:05:1311054 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11055 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711056 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5411057
[email protected]83039bb2011-12-09 18:43:5511058 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5411059
mmenkee65e7af2015-10-13 17:16:4211060 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5411061
[email protected]262eec82013-03-19 21:01:3611062 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011063 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5411064
[email protected]49639fa2011-12-20 23:22:4111065 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5411066 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4111067 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:5411068
11069 const HttpResponseInfo* response = trans->GetResponseInfo();
11070 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011071 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5411072 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11073
11074 std::string response_data;
11075 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11076 EXPECT_EQ("hello world", response_data);
11077
11078 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2311079 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4011080 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5311081 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2711082 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:4211083 CreateSecureSpdySession(session.get(), key, BoundNetLog());
[email protected]02b0c342010-09-25 21:09:3811084
[email protected]90499482013-06-01 00:39:5011085 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5411086
[email protected]49639fa2011-12-20 23:22:4111087 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5411088 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4111089 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:5411090
11091 response = trans->GetResponseInfo();
11092 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011093 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0211094 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5311095 EXPECT_TRUE(response->was_fetched_via_spdy);
11096 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5411097
11098 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11099 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4211100}
11101
[email protected]044de0642010-06-17 10:42:1511102// GenerateAuthToken is a mighty big test.
11103// It tests all permutation of GenerateAuthToken behavior:
11104// - Synchronous and Asynchronous completion.
11105// - OK or error on completion.
11106// - Direct connection, non-authenticating proxy, and authenticating proxy.
11107// - HTTP or HTTPS backend (to include proxy tunneling).
11108// - Non-authenticating and authenticating backend.
11109//
[email protected]fe3b7dc2012-02-03 19:52:0911110// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1511111// problems generating an auth token for an authenticating proxy, we don't
11112// need to test all permutations of the backend server).
11113//
11114// The test proceeds by going over each of the configuration cases, and
11115// potentially running up to three rounds in each of the tests. The TestConfig
11116// specifies both the configuration for the test as well as the expectations
11117// for the results.
[email protected]23e482282013-06-14 16:08:0211118TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5011119 static const char kServer[] = "http://www.example.com";
11120 static const char kSecureServer[] = "https://www.example.com";
11121 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1511122 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
11123
11124 enum AuthTiming {
11125 AUTH_NONE,
11126 AUTH_SYNC,
11127 AUTH_ASYNC,
11128 };
11129
11130 const MockWrite kGet(
11131 "GET / HTTP/1.1\r\n"
11132 "Host: www.example.com\r\n"
11133 "Connection: keep-alive\r\n\r\n");
11134 const MockWrite kGetProxy(
11135 "GET http://www.example.com/ HTTP/1.1\r\n"
11136 "Host: www.example.com\r\n"
11137 "Proxy-Connection: keep-alive\r\n\r\n");
11138 const MockWrite kGetAuth(
11139 "GET / HTTP/1.1\r\n"
11140 "Host: www.example.com\r\n"
11141 "Connection: keep-alive\r\n"
11142 "Authorization: auth_token\r\n\r\n");
11143 const MockWrite kGetProxyAuth(
11144 "GET http://www.example.com/ HTTP/1.1\r\n"
11145 "Host: www.example.com\r\n"
11146 "Proxy-Connection: keep-alive\r\n"
11147 "Proxy-Authorization: auth_token\r\n\r\n");
11148 const MockWrite kGetAuthThroughProxy(
11149 "GET http://www.example.com/ HTTP/1.1\r\n"
11150 "Host: www.example.com\r\n"
11151 "Proxy-Connection: keep-alive\r\n"
11152 "Authorization: auth_token\r\n\r\n");
11153 const MockWrite kGetAuthWithProxyAuth(
11154 "GET http://www.example.com/ HTTP/1.1\r\n"
11155 "Host: www.example.com\r\n"
11156 "Proxy-Connection: keep-alive\r\n"
11157 "Proxy-Authorization: auth_token\r\n"
11158 "Authorization: auth_token\r\n\r\n");
11159 const MockWrite kConnect(
11160 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711161 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1511162 "Proxy-Connection: keep-alive\r\n\r\n");
11163 const MockWrite kConnectProxyAuth(
11164 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711165 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1511166 "Proxy-Connection: keep-alive\r\n"
11167 "Proxy-Authorization: auth_token\r\n\r\n");
11168
11169 const MockRead kSuccess(
11170 "HTTP/1.1 200 OK\r\n"
11171 "Content-Type: text/html; charset=iso-8859-1\r\n"
11172 "Content-Length: 3\r\n\r\n"
11173 "Yes");
11174 const MockRead kFailure(
11175 "Should not be called.");
11176 const MockRead kServerChallenge(
11177 "HTTP/1.1 401 Unauthorized\r\n"
11178 "WWW-Authenticate: Mock realm=server\r\n"
11179 "Content-Type: text/html; charset=iso-8859-1\r\n"
11180 "Content-Length: 14\r\n\r\n"
11181 "Unauthorized\r\n");
11182 const MockRead kProxyChallenge(
11183 "HTTP/1.1 407 Unauthorized\r\n"
11184 "Proxy-Authenticate: Mock realm=proxy\r\n"
11185 "Proxy-Connection: close\r\n"
11186 "Content-Type: text/html; charset=iso-8859-1\r\n"
11187 "Content-Length: 14\r\n\r\n"
11188 "Unauthorized\r\n");
11189 const MockRead kProxyConnected(
11190 "HTTP/1.1 200 Connection Established\r\n\r\n");
11191
11192 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
11193 // no constructors, but the C++ compiler on Windows warns about
11194 // unspecified data in compound literals. So, moved to using constructors,
11195 // and TestRound's created with the default constructor should not be used.
11196 struct TestRound {
11197 TestRound()
11198 : expected_rv(ERR_UNEXPECTED),
11199 extra_write(NULL),
11200 extra_read(NULL) {
11201 }
11202 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
11203 int expected_rv_arg)
11204 : write(write_arg),
11205 read(read_arg),
11206 expected_rv(expected_rv_arg),
11207 extra_write(NULL),
11208 extra_read(NULL) {
11209 }
11210 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
11211 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0111212 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1511213 : write(write_arg),
11214 read(read_arg),
11215 expected_rv(expected_rv_arg),
11216 extra_write(extra_write_arg),
11217 extra_read(extra_read_arg) {
11218 }
11219 MockWrite write;
11220 MockRead read;
11221 int expected_rv;
11222 const MockWrite* extra_write;
11223 const MockRead* extra_read;
11224 };
11225
11226 static const int kNoSSL = 500;
11227
11228 struct TestConfig {
thestig9d3bb0c2015-01-24 00:49:5111229 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1511230 AuthTiming proxy_auth_timing;
11231 int proxy_auth_rv;
thestig9d3bb0c2015-01-24 00:49:5111232 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1511233 AuthTiming server_auth_timing;
11234 int server_auth_rv;
11235 int num_auth_rounds;
11236 int first_ssl_round;
11237 TestRound rounds[3];
11238 } test_configs[] = {
11239 // Non-authenticating HTTP server with a direct connection.
11240 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
11241 { TestRound(kGet, kSuccess, OK)}},
11242 // Authenticating HTTP server with a direct connection.
11243 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
11244 { TestRound(kGet, kServerChallenge, OK),
11245 TestRound(kGetAuth, kSuccess, OK)}},
11246 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
11247 { TestRound(kGet, kServerChallenge, OK),
11248 TestRound(kGetAuth, kFailure, kAuthErr)}},
11249 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
11250 { TestRound(kGet, kServerChallenge, OK),
11251 TestRound(kGetAuth, kSuccess, OK)}},
11252 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
11253 { TestRound(kGet, kServerChallenge, OK),
11254 TestRound(kGetAuth, kFailure, kAuthErr)}},
11255 // Non-authenticating HTTP server through a non-authenticating proxy.
11256 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
11257 { TestRound(kGetProxy, kSuccess, OK)}},
11258 // Authenticating HTTP server through a non-authenticating proxy.
11259 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
11260 { TestRound(kGetProxy, kServerChallenge, OK),
11261 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
11262 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
11263 { TestRound(kGetProxy, kServerChallenge, OK),
11264 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
11265 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
11266 { TestRound(kGetProxy, kServerChallenge, OK),
11267 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
11268 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
11269 { TestRound(kGetProxy, kServerChallenge, OK),
11270 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
11271 // Non-authenticating HTTP server through an authenticating proxy.
11272 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
11273 { TestRound(kGetProxy, kProxyChallenge, OK),
11274 TestRound(kGetProxyAuth, kSuccess, OK)}},
11275 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
11276 { TestRound(kGetProxy, kProxyChallenge, OK),
11277 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
11278 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
11279 { TestRound(kGetProxy, kProxyChallenge, OK),
11280 TestRound(kGetProxyAuth, kSuccess, OK)}},
11281 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
11282 { TestRound(kGetProxy, kProxyChallenge, OK),
11283 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
11284 // Authenticating HTTP server through an authenticating proxy.
11285 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
11286 { TestRound(kGetProxy, kProxyChallenge, OK),
11287 TestRound(kGetProxyAuth, kServerChallenge, OK),
11288 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11289 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
11290 { TestRound(kGetProxy, kProxyChallenge, OK),
11291 TestRound(kGetProxyAuth, kServerChallenge, OK),
11292 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11293 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
11294 { TestRound(kGetProxy, kProxyChallenge, OK),
11295 TestRound(kGetProxyAuth, kServerChallenge, OK),
11296 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11297 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
11298 { TestRound(kGetProxy, kProxyChallenge, OK),
11299 TestRound(kGetProxyAuth, kServerChallenge, OK),
11300 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11301 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
11302 { TestRound(kGetProxy, kProxyChallenge, OK),
11303 TestRound(kGetProxyAuth, kServerChallenge, OK),
11304 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11305 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
11306 { TestRound(kGetProxy, kProxyChallenge, OK),
11307 TestRound(kGetProxyAuth, kServerChallenge, OK),
11308 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11309 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
11310 { TestRound(kGetProxy, kProxyChallenge, OK),
11311 TestRound(kGetProxyAuth, kServerChallenge, OK),
11312 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11313 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
11314 { TestRound(kGetProxy, kProxyChallenge, OK),
11315 TestRound(kGetProxyAuth, kServerChallenge, OK),
11316 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11317 // Non-authenticating HTTPS server with a direct connection.
11318 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
11319 { TestRound(kGet, kSuccess, OK)}},
11320 // Authenticating HTTPS server with a direct connection.
11321 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
11322 { TestRound(kGet, kServerChallenge, OK),
11323 TestRound(kGetAuth, kSuccess, OK)}},
11324 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
11325 { TestRound(kGet, kServerChallenge, OK),
11326 TestRound(kGetAuth, kFailure, kAuthErr)}},
11327 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
11328 { TestRound(kGet, kServerChallenge, OK),
11329 TestRound(kGetAuth, kSuccess, OK)}},
11330 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
11331 { TestRound(kGet, kServerChallenge, OK),
11332 TestRound(kGetAuth, kFailure, kAuthErr)}},
11333 // Non-authenticating HTTPS server with a non-authenticating proxy.
11334 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
11335 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
11336 // Authenticating HTTPS server through a non-authenticating proxy.
11337 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
11338 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11339 TestRound(kGetAuth, kSuccess, OK)}},
11340 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
11341 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11342 TestRound(kGetAuth, kFailure, kAuthErr)}},
11343 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
11344 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11345 TestRound(kGetAuth, kSuccess, OK)}},
11346 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
11347 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11348 TestRound(kGetAuth, kFailure, kAuthErr)}},
11349 // Non-Authenticating HTTPS server through an authenticating proxy.
11350 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
11351 { TestRound(kConnect, kProxyChallenge, OK),
11352 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
11353 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
11354 { TestRound(kConnect, kProxyChallenge, OK),
11355 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
11356 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
11357 { TestRound(kConnect, kProxyChallenge, OK),
11358 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
11359 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
11360 { TestRound(kConnect, kProxyChallenge, OK),
11361 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
11362 // Authenticating HTTPS server through an authenticating proxy.
11363 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11364 { TestRound(kConnect, kProxyChallenge, OK),
11365 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11366 &kGet, &kServerChallenge),
11367 TestRound(kGetAuth, kSuccess, OK)}},
11368 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11369 { TestRound(kConnect, kProxyChallenge, OK),
11370 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11371 &kGet, &kServerChallenge),
11372 TestRound(kGetAuth, kFailure, kAuthErr)}},
11373 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11374 { TestRound(kConnect, kProxyChallenge, OK),
11375 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11376 &kGet, &kServerChallenge),
11377 TestRound(kGetAuth, kSuccess, OK)}},
11378 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11379 { TestRound(kConnect, kProxyChallenge, OK),
11380 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11381 &kGet, &kServerChallenge),
11382 TestRound(kGetAuth, kFailure, kAuthErr)}},
11383 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11384 { TestRound(kConnect, kProxyChallenge, OK),
11385 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11386 &kGet, &kServerChallenge),
11387 TestRound(kGetAuth, kSuccess, OK)}},
11388 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11389 { TestRound(kConnect, kProxyChallenge, OK),
11390 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11391 &kGet, &kServerChallenge),
11392 TestRound(kGetAuth, kFailure, kAuthErr)}},
11393 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11394 { TestRound(kConnect, kProxyChallenge, OK),
11395 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11396 &kGet, &kServerChallenge),
11397 TestRound(kGetAuth, kSuccess, OK)}},
11398 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11399 { TestRound(kConnect, kProxyChallenge, OK),
11400 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11401 &kGet, &kServerChallenge),
11402 TestRound(kGetAuth, kFailure, kAuthErr)}},
11403 };
11404
viettrungluue4a8b882014-10-16 06:17:3811405 for (size_t i = 0; i < arraysize(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:0811406 HttpAuthHandlerMock::Factory* auth_factory(
11407 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711408 session_deps_.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:1511409 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:2611410
11411 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1511412 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:0811413 for (int n = 0; n < 2; n++) {
11414 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11415 std::string auth_challenge = "Mock realm=proxy";
11416 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2411417 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11418 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0811419 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
11420 origin, BoundNetLog());
11421 auth_handler->SetGenerateExpectation(
11422 test_config.proxy_auth_timing == AUTH_ASYNC,
11423 test_config.proxy_auth_rv);
11424 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
11425 }
[email protected]044de0642010-06-17 10:42:1511426 }
11427 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0011428 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1511429 std::string auth_challenge = "Mock realm=server";
11430 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2411431 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11432 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1511433 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
11434 origin, BoundNetLog());
11435 auth_handler->SetGenerateExpectation(
11436 test_config.server_auth_timing == AUTH_ASYNC,
11437 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:0811438 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1511439 }
11440 if (test_config.proxy_url) {
rdsmith82957ad2015-09-16 19:42:0311441 session_deps_.proxy_service =
11442 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:1511443 } else {
rdsmith82957ad2015-09-16 19:42:0311444 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1511445 }
11446
11447 HttpRequestInfo request;
11448 request.method = "GET";
11449 request.url = GURL(test_config.server_url);
11450 request.load_flags = 0;
11451
mmenkee65e7af2015-10-13 17:16:4211452 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1511453
rchcb68dc62015-05-21 04:45:3611454 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
11455
11456 std::vector<std::vector<MockRead>> mock_reads(1);
11457 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1511458 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11459 const TestRound& read_write_round = test_config.rounds[round];
11460
11461 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3611462 mock_reads.back().push_back(read_write_round.read);
11463 mock_writes.back().push_back(read_write_round.write);
11464
11465 // kProxyChallenge uses Proxy-Connection: close which means that the
11466 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5411467 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3611468 mock_reads.push_back(std::vector<MockRead>());
11469 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1511470 }
11471
rchcb68dc62015-05-21 04:45:3611472 if (read_write_round.extra_read) {
11473 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1511474 }
rchcb68dc62015-05-21 04:45:3611475 if (read_write_round.extra_write) {
11476 mock_writes.back().push_back(*read_write_round.extra_write);
11477 }
[email protected]044de0642010-06-17 10:42:1511478
11479 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1511480 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0711481 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1511482 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3611483 }
[email protected]044de0642010-06-17 10:42:1511484
rchcb68dc62015-05-21 04:45:3611485 ScopedVector<StaticSocketDataProvider> data_providers;
11486 for (size_t i = 0; i < mock_reads.size(); ++i) {
11487 data_providers.push_back(new StaticSocketDataProvider(
davidben5f8b6bc2015-11-25 03:19:5411488 mock_reads[i].data(), mock_reads[i].size(), mock_writes[i].data(),
11489 mock_writes[i].size()));
rchcb68dc62015-05-21 04:45:3611490 session_deps_.socket_factory->AddSocketDataProvider(
11491 data_providers.back());
11492 }
11493
mmenkecc2298e2015-12-07 18:20:1811494 // Transaction must be created after DataProviders, so it's destroyed before
11495 // they are as well.
11496 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11497
rchcb68dc62015-05-21 04:45:3611498 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11499 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1511500 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4111501 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1511502 int rv;
11503 if (round == 0) {
[email protected]49639fa2011-12-20 23:22:4111504 rv = trans.Start(&request, callback.callback(), BoundNetLog());
[email protected]044de0642010-06-17 10:42:1511505 } else {
[email protected]49639fa2011-12-20 23:22:4111506 rv = trans.RestartWithAuth(
11507 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1511508 }
11509 if (rv == ERR_IO_PENDING)
11510 rv = callback.WaitForResult();
11511
11512 // Compare results with expected data.
11513 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:5011514 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5511515 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1511516 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
11517 continue;
11518 }
11519 if (round + 1 < test_config.num_auth_rounds) {
11520 EXPECT_FALSE(response->auth_challenge.get() == NULL);
11521 } else {
11522 EXPECT_TRUE(response->auth_challenge.get() == NULL);
11523 }
11524 }
[email protected]e5ae96a2010-04-14 20:12:4511525 }
11526}
11527
[email protected]23e482282013-06-14 16:08:0211528TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1411529 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1411530 HttpAuthHandlerMock::Factory* auth_factory(
11531 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711532 session_deps_.http_auth_handler_factory.reset(auth_factory);
rdsmith82957ad2015-09-16 19:42:0311533 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0711534 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
11535 session_deps_.host_resolver->set_synchronous_mode(true);
[email protected]c871bce92010-07-15 21:51:1411536
11537 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11538 auth_handler->set_connection_based(true);
11539 std::string auth_challenge = "Mock realm=server";
11540 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2411541 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11542 auth_challenge.end());
[email protected]c871bce92010-07-15 21:51:1411543 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
11544 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:0811545 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1411546
[email protected]c871bce92010-07-15 21:51:1411547 int rv = OK;
11548 const HttpResponseInfo* response = NULL;
11549 HttpRequestInfo request;
11550 request.method = "GET";
11551 request.url = origin;
11552 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:2711553
mmenkee65e7af2015-10-13 17:16:4211554 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1011555
11556 // Use a TCP Socket Pool with only one connection per group. This is used
11557 // to validate that the TCP socket is not released to the pool between
11558 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4211559 HttpNetworkSessionPeer session_peer(session.get());
[email protected]ab739042011-04-07 15:22:2811560 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:1011561 50, // Max sockets for pool
11562 1, // Max sockets per group
[email protected]bb88e1d32013-05-03 23:11:0711563 session_deps_.host_resolver.get(),
11564 session_deps_.socket_factory.get(),
11565 session_deps_.net_log);
[email protected]831e4a32013-11-14 02:14:4411566 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
11567 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:0211568 mock_pool_manager->SetTransportSocketPool(transport_pool);
dchenge3d1ddc2014-10-15 19:30:5111569 session_peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
[email protected]7ef4cbbb2011-02-06 11:19:1011570
[email protected]262eec82013-03-19 21:01:3611571 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011572 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111573 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1411574
11575 const MockWrite kGet(
11576 "GET / HTTP/1.1\r\n"
11577 "Host: www.example.com\r\n"
11578 "Connection: keep-alive\r\n\r\n");
11579 const MockWrite kGetAuth(
11580 "GET / HTTP/1.1\r\n"
11581 "Host: www.example.com\r\n"
11582 "Connection: keep-alive\r\n"
11583 "Authorization: auth_token\r\n\r\n");
11584
11585 const MockRead kServerChallenge(
11586 "HTTP/1.1 401 Unauthorized\r\n"
11587 "WWW-Authenticate: Mock realm=server\r\n"
11588 "Content-Type: text/html; charset=iso-8859-1\r\n"
11589 "Content-Length: 14\r\n\r\n"
11590 "Unauthorized\r\n");
11591 const MockRead kSuccess(
11592 "HTTP/1.1 200 OK\r\n"
11593 "Content-Type: text/html; charset=iso-8859-1\r\n"
11594 "Content-Length: 3\r\n\r\n"
11595 "Yes");
11596
11597 MockWrite writes[] = {
11598 // First round
11599 kGet,
11600 // Second round
11601 kGetAuth,
11602 // Third round
11603 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3011604 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1011605 kGetAuth,
11606 // Competing request
11607 kGet,
[email protected]c871bce92010-07-15 21:51:1411608 };
11609 MockRead reads[] = {
11610 // First round
11611 kServerChallenge,
11612 // Second round
11613 kServerChallenge,
11614 // Third round
[email protected]eca50e122010-09-11 14:03:3011615 kServerChallenge,
11616 // Fourth round
[email protected]c871bce92010-07-15 21:51:1411617 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1011618 // Competing response
11619 kSuccess,
[email protected]c871bce92010-07-15 21:51:1411620 };
11621 StaticSocketDataProvider data_provider(reads, arraysize(reads),
11622 writes, arraysize(writes));
[email protected]bb88e1d32013-05-03 23:11:0711623 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1411624
thestig9d3bb0c2015-01-24 00:49:5111625 const char kSocketGroup[] = "www.example.com:80";
[email protected]7ef4cbbb2011-02-06 11:19:1011626
11627 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1411628 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111629 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]c871bce92010-07-15 21:51:1411630 if (rv == ERR_IO_PENDING)
11631 rv = callback.WaitForResult();
11632 EXPECT_EQ(OK, rv);
11633 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011634 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411635 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811636 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411637
[email protected]7ef4cbbb2011-02-06 11:19:1011638 // In between rounds, another request comes in for the same domain.
11639 // It should not be able to grab the TCP socket that trans has already
11640 // claimed.
11641 scoped_ptr<HttpTransaction> trans_compete(
[email protected]90499482013-06-01 00:39:5011642 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111643 TestCompletionCallback callback_compete;
11644 rv = trans_compete->Start(
11645 &request, callback_compete.callback(), BoundNetLog());
[email protected]7ef4cbbb2011-02-06 11:19:1011646 EXPECT_EQ(ERR_IO_PENDING, rv);
11647 // callback_compete.WaitForResult at this point would stall forever,
11648 // since the HttpNetworkTransaction does not release the request back to
11649 // the pool until after authentication completes.
11650
11651 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1411652 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111653 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411654 if (rv == ERR_IO_PENDING)
11655 rv = callback.WaitForResult();
11656 EXPECT_EQ(OK, rv);
11657 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011658 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411659 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811660 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411661
[email protected]7ef4cbbb2011-02-06 11:19:1011662 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1411663 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111664 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411665 if (rv == ERR_IO_PENDING)
11666 rv = callback.WaitForResult();
11667 EXPECT_EQ(OK, rv);
11668 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011669 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411670 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811671 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:3011672
[email protected]7ef4cbbb2011-02-06 11:19:1011673 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3011674 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111675 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3011676 if (rv == ERR_IO_PENDING)
11677 rv = callback.WaitForResult();
11678 EXPECT_EQ(OK, rv);
11679 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011680 ASSERT_TRUE(response != NULL);
[email protected]eca50e122010-09-11 14:03:3011681 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811682 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011683
11684 // Read the body since the fourth round was successful. This will also
11685 // release the socket back to the pool.
11686 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
[email protected]90499482013-06-01 00:39:5011687 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011688 if (rv == ERR_IO_PENDING)
11689 rv = callback.WaitForResult();
11690 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011691 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011692 EXPECT_EQ(0, rv);
11693 // There are still 0 idle sockets, since the trans_compete transaction
11694 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:2811695 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011696
11697 // The competing request can now finish. Wait for the headers and then
11698 // read the body.
11699 rv = callback_compete.WaitForResult();
11700 EXPECT_EQ(OK, rv);
[email protected]90499482013-06-01 00:39:5011701 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011702 if (rv == ERR_IO_PENDING)
11703 rv = callback.WaitForResult();
11704 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011705 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011706 EXPECT_EQ(0, rv);
11707
11708 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:2811709 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411710}
11711
[email protected]65041fa2010-05-21 06:56:5311712// This tests the case that a request is issued via http instead of spdy after
11713// npn is negotiated.
[email protected]23e482282013-06-14 16:08:0211714TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
bnc55ff9da2015-08-19 18:42:3511715 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311716 NextProtoVector next_protos;
[email protected]0ce3af82013-07-22 16:17:1611717 next_protos.push_back(kProtoHTTP11);
[email protected]d7599122014-05-24 03:37:2311718 session_deps_.next_protos = next_protos;
11719
[email protected]65041fa2010-05-21 06:56:5311720 HttpRequestInfo request;
11721 request.method = "GET";
bncce36dca22015-04-21 22:11:2311722 request.url = GURL("https://www.example.org/");
[email protected]65041fa2010-05-21 06:56:5311723 request.load_flags = 0;
11724
11725 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311726 MockWrite(
11727 "GET / HTTP/1.1\r\n"
11728 "Host: www.example.org\r\n"
11729 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5311730 };
11731
[email protected]8a0fc822013-06-27 20:52:4311732 std::string alternate_protocol_http_header =
11733 GetAlternateProtocolHttpHeader();
11734
[email protected]65041fa2010-05-21 06:56:5311735 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211736 MockRead("HTTP/1.1 200 OK\r\n"),
11737 MockRead(alternate_protocol_http_header.c_str()),
11738 MockRead("\r\n"),
11739 MockRead("hello world"),
11740 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5311741 };
11742
[email protected]8ddf8322012-02-23 18:08:0611743 SSLSocketDataProvider ssl(ASYNC, OK);
davidben6974bf72015-04-27 17:52:4811744 ssl.SetNextProto(kProtoHTTP11);
[email protected]65041fa2010-05-21 06:56:5311745
[email protected]bb88e1d32013-05-03 23:11:0711746 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5311747
11748 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11749 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0711750 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5311751
[email protected]49639fa2011-12-20 23:22:4111752 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5311753
mmenkee65e7af2015-10-13 17:16:4211754 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3611755 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011756 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]65041fa2010-05-21 06:56:5311757
[email protected]49639fa2011-12-20 23:22:4111758 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]65041fa2010-05-21 06:56:5311759
11760 EXPECT_EQ(ERR_IO_PENDING, rv);
11761 EXPECT_EQ(OK, callback.WaitForResult());
11762
11763 const HttpResponseInfo* response = trans->GetResponseInfo();
11764 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011765 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]65041fa2010-05-21 06:56:5311766 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11767
11768 std::string response_data;
11769 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11770 EXPECT_EQ("hello world", response_data);
11771
11772 EXPECT_FALSE(response->was_fetched_via_spdy);
11773 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]65041fa2010-05-21 06:56:5311774}
[email protected]26ef6582010-06-24 02:30:4711775
bnc55ff9da2015-08-19 18:42:3511776// Simulate the SSL handshake completing with an NPN negotiation followed by an
11777// immediate server closing of the socket.
11778// Regression test for https://crbug.com/46369.
[email protected]23e482282013-06-14 16:08:0211779TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
bnc55ff9da2015-08-19 18:42:3511780 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311781 session_deps_.next_protos = SpdyNextProtos();
[email protected]26ef6582010-06-24 02:30:4711782
11783 HttpRequestInfo request;
11784 request.method = "GET";
bncce36dca22015-04-21 22:11:2311785 request.url = GURL("https://www.example.org/");
[email protected]26ef6582010-06-24 02:30:4711786 request.load_flags = 0;
11787
[email protected]8ddf8322012-02-23 18:08:0611788 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811789 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0711790 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4711791
[email protected]cdf8f7e72013-05-23 10:56:4611792 scoped_ptr<SpdyFrame> req(
11793 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1311794 MockWrite spdy_writes[] = {CreateMockWrite(*req, 1)};
[email protected]26ef6582010-06-24 02:30:4711795
11796 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0611797 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4711798 };
11799
rch8e6c6c42015-05-01 14:05:1311800 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11801 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711802 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4711803
[email protected]49639fa2011-12-20 23:22:4111804 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4711805
mmenkee65e7af2015-10-13 17:16:4211806 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3611807 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011808 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]26ef6582010-06-24 02:30:4711809
[email protected]49639fa2011-12-20 23:22:4111810 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]26ef6582010-06-24 02:30:4711811 EXPECT_EQ(ERR_IO_PENDING, rv);
11812 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
[email protected]26ef6582010-06-24 02:30:4711813}
[email protected]65d34382010-07-01 18:12:2611814
[email protected]795cbf82013-07-22 09:37:2711815// A subclass of HttpAuthHandlerMock that records the request URL when
11816// it gets it. This is needed since the auth handler may get destroyed
11817// before we get a chance to query it.
11818class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
11819 public:
11820 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
11821
dchengb03027d2014-10-21 12:00:2011822 ~UrlRecordingHttpAuthHandlerMock() override {}
[email protected]795cbf82013-07-22 09:37:2711823
11824 protected:
dchengb03027d2014-10-21 12:00:2011825 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
11826 const HttpRequestInfo* request,
11827 const CompletionCallback& callback,
11828 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2711829 *url_ = request->url;
11830 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
11831 credentials, request, callback, auth_token);
11832 }
11833
11834 private:
11835 GURL* url_;
11836};
11837
bnc55ff9da2015-08-19 18:42:3511838// This test ensures that the URL passed into the proxy is upgraded to https
11839// when doing an Alternate Protocol upgrade.
[email protected]23e482282013-06-14 16:08:0211840TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
bnc55ff9da2015-08-19 18:42:3511841 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311842 session_deps_.next_protos = SpdyNextProtos();
[email protected]f45c1ee2010-08-03 00:54:3011843
rdsmith82957ad2015-09-16 19:42:0311844 session_deps_.proxy_service =
11845 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5111846 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711847 session_deps_.net_log = &net_log;
[email protected]795cbf82013-07-22 09:37:2711848 GURL request_url;
11849 {
11850 HttpAuthHandlerMock::Factory* auth_factory =
11851 new HttpAuthHandlerMock::Factory();
11852 UrlRecordingHttpAuthHandlerMock* auth_handler =
11853 new UrlRecordingHttpAuthHandlerMock(&request_url);
11854 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
11855 auth_factory->set_do_init_from_challenge(true);
11856 session_deps_.http_auth_handler_factory.reset(auth_factory);
11857 }
[email protected]f45c1ee2010-08-03 00:54:3011858
11859 HttpRequestInfo request;
11860 request.method = "GET";
bncce36dca22015-04-21 22:11:2311861 request.url = GURL("http://www.example.org");
[email protected]f45c1ee2010-08-03 00:54:3011862 request.load_flags = 0;
11863
11864 // First round goes unauthenticated through the proxy.
11865 MockWrite data_writes_1[] = {
bncce36dca22015-04-21 22:11:2311866 MockWrite(
11867 "GET http://www.example.org/ HTTP/1.1\r\n"
11868 "Host: www.example.org\r\n"
11869 "Proxy-Connection: keep-alive\r\n"
11870 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011871 };
11872 MockRead data_reads_1[] = {
[email protected]8ddf8322012-02-23 18:08:0611873 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
bnc33b8cef42014-11-19 17:30:3811874 MockRead("HTTP/1.1 200 OK\r\n"),
11875 MockRead("Alternate-Protocol: 443:"),
11876 MockRead(GetAlternateProtocolFromParam()),
11877 MockRead("\r\n"),
11878 MockRead("Proxy-Connection: close\r\n"),
11879 MockRead("\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011880 };
11881 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
11882 data_writes_1, arraysize(data_writes_1));
11883
bncce36dca22015-04-21 22:11:2311884 // Second round tries to tunnel to www.example.org due to the
[email protected]f45c1ee2010-08-03 00:54:3011885 // Alternate-Protocol announcement in the first round. It fails due
11886 // to a proxy authentication challenge.
bncce36dca22015-04-21 22:11:2311887 // After the failure, a tunnel is established to www.example.org using
[email protected]394816e92010-08-03 07:38:5911888 // Proxy-Authorization headers. There is then a SPDY request round.
11889 //
[email protected]fe3b7dc2012-02-03 19:52:0911890 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
11891 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
11892 // does a Disconnect and Connect on the same socket, rather than trying
11893 // to obtain a new one.
11894 //
[email protected]394816e92010-08-03 07:38:5911895 // NOTE: Originally, the proxy response to the second CONNECT request
11896 // simply returned another 407 so the unit test could skip the SSL connection
11897 // establishment and SPDY framing issues. Alas, the
11898 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:3011899 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:5911900
[email protected]cdf8f7e72013-05-23 10:56:4611901 scoped_ptr<SpdyFrame> req(
11902 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]23e482282013-06-14 16:08:0211903 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11904 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]f45c1ee2010-08-03 00:54:3011905
[email protected]394816e92010-08-03 07:38:5911906 MockWrite data_writes_2[] = {
bncce36dca22015-04-21 22:11:2311907 // First connection attempt without Proxy-Authorization.
rch8e6c6c42015-05-01 14:05:1311908 MockWrite(ASYNC, 0,
11909 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711910 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1311911 "Proxy-Connection: keep-alive\r\n"
11912 "\r\n"),
[email protected]394816e92010-08-03 07:38:5911913
bncce36dca22015-04-21 22:11:2311914 // Second connection attempt with Proxy-Authorization.
rch8e6c6c42015-05-01 14:05:1311915 MockWrite(ASYNC, 2,
11916 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711917 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1311918 "Proxy-Connection: keep-alive\r\n"
11919 "Proxy-Authorization: auth_token\r\n"
11920 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011921
bncce36dca22015-04-21 22:11:2311922 // SPDY request
rch8e6c6c42015-05-01 14:05:1311923 CreateMockWrite(*req, 4),
[email protected]f45c1ee2010-08-03 00:54:3011924 };
[email protected]394816e92010-08-03 07:38:5911925 MockRead data_reads_2[] = {
rch8e6c6c42015-05-01 14:05:1311926 // First connection attempt fails
mmenkee71e15332015-10-07 16:39:5411927 MockRead(ASYNC, 1,
11928 "HTTP/1.1 407 Unauthorized\r\n"
11929 "Proxy-Authenticate: Mock\r\n"
11930 "Content-Length: 0\r\n"
11931 "Proxy-Connection: keep-alive\r\n"
11932 "\r\n"),
[email protected]394816e92010-08-03 07:38:5911933
rch8e6c6c42015-05-01 14:05:1311934 // Second connection attempt passes
mmenkee71e15332015-10-07 16:39:5411935 MockRead(ASYNC, 3, "HTTP/1.1 200 Connected\r\n\r\n"),
[email protected]394816e92010-08-03 07:38:5911936
rch8e6c6c42015-05-01 14:05:1311937 // SPDY response
mmenkee71e15332015-10-07 16:39:5411938 CreateMockRead(*resp.get(), 5), CreateMockRead(*data.get(), 6),
rch8e6c6c42015-05-01 14:05:1311939 MockRead(ASYNC, 0, 0, 7),
[email protected]394816e92010-08-03 07:38:5911940 };
rch8e6c6c42015-05-01 14:05:1311941 SequencedSocketData data_2(data_reads_2, arraysize(data_reads_2),
11942 data_writes_2, arraysize(data_writes_2));
[email protected]f45c1ee2010-08-03 00:54:3011943
[email protected]8ddf8322012-02-23 18:08:0611944 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811945 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2311946 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11947 ASSERT_TRUE(ssl.cert.get());
[email protected]f45c1ee2010-08-03 00:54:3011948
[email protected]d973e99a2012-02-17 21:02:3611949 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5511950 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
11951 NULL, 0, NULL, 0);
11952 hanging_non_alternate_protocol_socket.set_connect_data(
11953 never_finishing_connect);
11954
[email protected]bb88e1d32013-05-03 23:11:0711955 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
11956 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
11957 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11958 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5511959 &hanging_non_alternate_protocol_socket);
mmenkee65e7af2015-10-13 17:16:4211960 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f45c1ee2010-08-03 00:54:3011961
11962 // First round should work and provide the Alternate-Protocol state.
[email protected]49639fa2011-12-20 23:22:4111963 TestCompletionCallback callback_1;
[email protected]262eec82013-03-19 21:01:3611964 scoped_ptr<HttpTransaction> trans_1(
[email protected]90499482013-06-01 00:39:5011965 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111966 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:3011967 EXPECT_EQ(ERR_IO_PENDING, rv);
11968 EXPECT_EQ(OK, callback_1.WaitForResult());
11969
11970 // Second round should attempt a tunnel connect and get an auth challenge.
[email protected]49639fa2011-12-20 23:22:4111971 TestCompletionCallback callback_2;
[email protected]262eec82013-03-19 21:01:3611972 scoped_ptr<HttpTransaction> trans_2(
[email protected]90499482013-06-01 00:39:5011973 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111974 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:3011975 EXPECT_EQ(ERR_IO_PENDING, rv);
11976 EXPECT_EQ(OK, callback_2.WaitForResult());
11977 const HttpResponseInfo* response = trans_2->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011978 ASSERT_TRUE(response != NULL);
[email protected]f45c1ee2010-08-03 00:54:3011979 ASSERT_FALSE(response->auth_challenge.get() == NULL);
11980
11981 // Restart with auth. Tunnel should work and response received.
[email protected]49639fa2011-12-20 23:22:4111982 TestCompletionCallback callback_3;
11983 rv = trans_2->RestartWithAuth(
11984 AuthCredentials(kFoo, kBar), callback_3.callback());
[email protected]f45c1ee2010-08-03 00:54:3011985 EXPECT_EQ(ERR_IO_PENDING, rv);
11986 EXPECT_EQ(OK, callback_3.WaitForResult());
11987
11988 // After all that work, these two lines (or actually, just the scheme) are
11989 // what this test is all about. Make sure it happens correctly.
[email protected]f45c1ee2010-08-03 00:54:3011990 EXPECT_EQ("https", request_url.scheme());
bncce36dca22015-04-21 22:11:2311991 EXPECT_EQ("www.example.org", request_url.host());
[email protected]f45c1ee2010-08-03 00:54:3011992
[email protected]029c83b62013-01-24 05:28:2011993 LoadTimingInfo load_timing_info;
11994 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
11995 TestLoadTimingNotReusedWithPac(load_timing_info,
11996 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]8e6441ca2010-08-19 05:56:3811997}
11998
11999// Test that if we cancel the transaction as the connection is completing, that
12000// everything tears down correctly.
[email protected]23e482282013-06-14 16:08:0212001TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3812002 // Setup everything about the connection to complete synchronously, so that
12003 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
12004 // for is the callback from the HttpStreamRequest.
12005 // Then cancel the transaction.
12006 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3612007 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3812008 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0612009 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
12010 MockRead(SYNCHRONOUS, "hello world"),
12011 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3812012 };
12013
[email protected]8e6441ca2010-08-19 05:56:3812014 HttpRequestInfo request;
12015 request.method = "GET";
bncce36dca22015-04-21 22:11:2312016 request.url = GURL("http://www.example.org/");
[email protected]8e6441ca2010-08-19 05:56:3812017 request.load_flags = 0;
12018
[email protected]bb88e1d32013-05-03 23:11:0712019 session_deps_.host_resolver->set_synchronous_mode(true);
mmenkee65e7af2015-10-13 17:16:4212020 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:2712021 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4112022 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:2712023
[email protected]8e6441ca2010-08-19 05:56:3812024 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
12025 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712026 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3812027
[email protected]49639fa2011-12-20 23:22:4112028 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3812029
vishal.b62985ca92015-04-17 08:45:5112030 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4112031 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]8e6441ca2010-08-19 05:56:3812032 EXPECT_EQ(ERR_IO_PENDING, rv);
12033 trans.reset(); // Cancel the transaction here.
12034
[email protected]2da659e2013-05-23 20:51:3412035 base::MessageLoop::current()->RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3012036}
12037
[email protected]ecab6e052014-05-16 14:58:1212038// Test that if a transaction is cancelled after receiving the headers, the
12039// stream is drained properly and added back to the socket pool. The main
12040// purpose of this test is to make sure that an HttpStreamParser can be read
12041// from after the HttpNetworkTransaction and the objects it owns have been
12042// deleted.
12043// See http://crbug.com/368418
12044TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
12045 MockRead data_reads[] = {
12046 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
12047 MockRead(ASYNC, "Content-Length: 2\r\n"),
12048 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
12049 MockRead(ASYNC, "1"),
12050 // 2 async reads are necessary to trigger a ReadResponseBody call after the
12051 // HttpNetworkTransaction has been deleted.
12052 MockRead(ASYNC, "2"),
12053 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
12054 };
12055 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
12056 session_deps_.socket_factory->AddSocketDataProvider(&data);
12057
mmenkee65e7af2015-10-13 17:16:4212058 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1212059
12060 {
12061 HttpRequestInfo request;
12062 request.method = "GET";
bncce36dca22015-04-21 22:11:2312063 request.url = GURL("http://www.example.org/");
[email protected]ecab6e052014-05-16 14:58:1212064 request.load_flags = 0;
12065
dcheng48459ac22014-08-26 00:46:4112066 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1212067 TestCompletionCallback callback;
12068
12069 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
12070 EXPECT_EQ(ERR_IO_PENDING, rv);
12071 callback.WaitForResult();
12072
12073 const HttpResponseInfo* response = trans.GetResponseInfo();
12074 ASSERT_TRUE(response != NULL);
12075 EXPECT_TRUE(response->headers.get() != NULL);
12076 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12077
12078 // The transaction and HttpRequestInfo are deleted.
12079 }
12080
12081 // Let the HttpResponseBodyDrainer drain the socket.
12082 base::MessageLoop::current()->RunUntilIdle();
12083
12084 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4112085 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1212086}
12087
[email protected]76a505b2010-08-25 06:23:0012088// Test a basic GET request through a proxy.
[email protected]23e482282013-06-14 16:08:0212089TEST_P(HttpNetworkTransactionTest, ProxyGet) {
rdsmith82957ad2015-09-16 19:42:0312090 session_deps_.proxy_service =
12091 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112092 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712093 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4212094 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012095
[email protected]76a505b2010-08-25 06:23:0012096 HttpRequestInfo request;
12097 request.method = "GET";
bncce36dca22015-04-21 22:11:2312098 request.url = GURL("http://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012099
12100 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312101 MockWrite(
12102 "GET http://www.example.org/ HTTP/1.1\r\n"
12103 "Host: www.example.org\r\n"
12104 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012105 };
12106
12107 MockRead data_reads1[] = {
12108 MockRead("HTTP/1.1 200 OK\r\n"),
12109 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12110 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612111 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0012112 };
12113
12114 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12115 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712116 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0012117
[email protected]49639fa2011-12-20 23:22:4112118 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012119
[email protected]262eec82013-03-19 21:01:3612120 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012121 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]597a1ab2014-06-26 08:12:2712122 BeforeProxyHeadersSentHandler proxy_headers_handler;
12123 trans->SetBeforeProxyHeadersSentCallback(
12124 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
12125 base::Unretained(&proxy_headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5012126
[email protected]49639fa2011-12-20 23:22:4112127 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0012128 EXPECT_EQ(ERR_IO_PENDING, rv);
12129
12130 rv = callback1.WaitForResult();
12131 EXPECT_EQ(OK, rv);
12132
12133 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5012134 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:0012135
12136 EXPECT_TRUE(response->headers->IsKeepAlive());
12137 EXPECT_EQ(200, response->headers->response_code());
12138 EXPECT_EQ(100, response->headers->GetContentLength());
12139 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1512140 EXPECT_TRUE(
12141 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
[email protected]597a1ab2014-06-26 08:12:2712142 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
12143 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0012144 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2012145
12146 LoadTimingInfo load_timing_info;
12147 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12148 TestLoadTimingNotReusedWithPac(load_timing_info,
12149 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0012150}
12151
12152// Test a basic HTTPS GET request through a proxy.
[email protected]23e482282013-06-14 16:08:0212153TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
rdsmith82957ad2015-09-16 19:42:0312154 session_deps_.proxy_service =
12155 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112156 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712157 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4212158 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012159
[email protected]76a505b2010-08-25 06:23:0012160 HttpRequestInfo request;
12161 request.method = "GET";
bncce36dca22015-04-21 22:11:2312162 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012163
12164 // Since we have proxy, should try to establish tunnel.
12165 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1712166 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
12167 "Host: www.example.org:443\r\n"
12168 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012169
rsleevidb16bb02015-11-12 23:47:1712170 MockWrite("GET / HTTP/1.1\r\n"
12171 "Host: www.example.org\r\n"
12172 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012173 };
12174
12175 MockRead data_reads1[] = {
12176 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
12177
12178 MockRead("HTTP/1.1 200 OK\r\n"),
12179 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12180 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612181 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0012182 };
12183
12184 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12185 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712186 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0612187 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712188 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0012189
[email protected]49639fa2011-12-20 23:22:4112190 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012191
[email protected]262eec82013-03-19 21:01:3612192 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012193 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:5012194
[email protected]49639fa2011-12-20 23:22:4112195 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0012196 EXPECT_EQ(ERR_IO_PENDING, rv);
12197
12198 rv = callback1.WaitForResult();
12199 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:4612200 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4012201 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0012202 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012203 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0012204 NetLog::PHASE_NONE);
12205 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012206 entries, pos,
[email protected]76a505b2010-08-25 06:23:0012207 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12208 NetLog::PHASE_NONE);
12209
12210 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5012211 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:0012212
12213 EXPECT_TRUE(response->headers->IsKeepAlive());
12214 EXPECT_EQ(200, response->headers->response_code());
12215 EXPECT_EQ(100, response->headers->GetContentLength());
12216 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
12217 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1512218 EXPECT_TRUE(
12219 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
[email protected]029c83b62013-01-24 05:28:2012220
12221 LoadTimingInfo load_timing_info;
12222 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12223 TestLoadTimingNotReusedWithPac(load_timing_info,
12224 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0012225}
12226
rsleevidb16bb02015-11-12 23:47:1712227// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
12228// literal host.
12229TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
12230 session_deps_.proxy_service =
12231 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
12232 BoundTestNetLog log;
12233 session_deps_.net_log = log.bound().net_log();
12234 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12235
12236 HttpRequestInfo request;
12237 request.method = "GET";
12238 request.url = GURL("https://[::1]:443/");
12239
12240 // Since we have proxy, should try to establish tunnel.
12241 MockWrite data_writes1[] = {
12242 MockWrite("CONNECT [::1]:443 HTTP/1.1\r\n"
12243 "Host: [::1]:443\r\n"
12244 "Proxy-Connection: keep-alive\r\n\r\n"),
12245
12246 MockWrite("GET / HTTP/1.1\r\n"
12247 "Host: [::1]\r\n"
12248 "Connection: keep-alive\r\n\r\n"),
12249 };
12250
12251 MockRead data_reads1[] = {
12252 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
12253
12254 MockRead("HTTP/1.1 200 OK\r\n"),
12255 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12256 MockRead("Content-Length: 100\r\n\r\n"),
12257 MockRead(SYNCHRONOUS, OK),
12258 };
12259
12260 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12261 data_writes1, arraysize(data_writes1));
12262 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12263 SSLSocketDataProvider ssl(ASYNC, OK);
12264 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12265
12266 TestCompletionCallback callback1;
12267
12268 scoped_ptr<HttpTransaction> trans(
12269 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12270
12271 int rv = trans->Start(&request, callback1.callback(), log.bound());
12272 EXPECT_EQ(ERR_IO_PENDING, rv);
12273
12274 rv = callback1.WaitForResult();
12275 EXPECT_EQ(OK, rv);
12276 TestNetLogEntry::List entries;
12277 log.GetEntries(&entries);
12278 size_t pos = ExpectLogContainsSomewhere(
12279 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
12280 NetLog::PHASE_NONE);
12281 ExpectLogContainsSomewhere(
12282 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12283 NetLog::PHASE_NONE);
12284
12285 const HttpResponseInfo* response = trans->GetResponseInfo();
12286 ASSERT_TRUE(response != NULL);
12287
12288 EXPECT_TRUE(response->headers->IsKeepAlive());
12289 EXPECT_EQ(200, response->headers->response_code());
12290 EXPECT_EQ(100, response->headers->GetContentLength());
12291 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
12292 EXPECT_TRUE(response->was_fetched_via_proxy);
12293 EXPECT_TRUE(
12294 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
12295
12296 LoadTimingInfo load_timing_info;
12297 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12298 TestLoadTimingNotReusedWithPac(load_timing_info,
12299 CONNECT_TIMING_HAS_SSL_TIMES);
12300}
12301
[email protected]76a505b2010-08-25 06:23:0012302// Test a basic HTTPS GET request through a proxy, but the server hangs up
12303// while establishing the tunnel.
[email protected]23e482282013-06-14 16:08:0212304TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
rdsmith82957ad2015-09-16 19:42:0312305 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112306 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712307 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4212308 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012309
[email protected]76a505b2010-08-25 06:23:0012310 HttpRequestInfo request;
12311 request.method = "GET";
bncce36dca22015-04-21 22:11:2312312 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012313
12314 // Since we have proxy, should try to establish tunnel.
12315 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1712316 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
12317 "Host: www.example.org:443\r\n"
12318 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012319
rsleevidb16bb02015-11-12 23:47:1712320 MockWrite("GET / HTTP/1.1\r\n"
12321 "Host: www.example.org\r\n"
12322 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012323 };
12324
12325 MockRead data_reads1[] = {
[email protected]8ddf8322012-02-23 18:08:0612326 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]76a505b2010-08-25 06:23:0012327 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612328 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0012329 };
12330
12331 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12332 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712333 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0612334 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712335 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0012336
[email protected]49639fa2011-12-20 23:22:4112337 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012338
[email protected]262eec82013-03-19 21:01:3612339 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012340 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:5012341
[email protected]49639fa2011-12-20 23:22:4112342 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0012343 EXPECT_EQ(ERR_IO_PENDING, rv);
12344
12345 rv = callback1.WaitForResult();
12346 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
mmenke43758e62015-05-04 21:09:4612347 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4012348 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0012349 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012350 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0012351 NetLog::PHASE_NONE);
12352 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012353 entries, pos,
[email protected]76a505b2010-08-25 06:23:0012354 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12355 NetLog::PHASE_NONE);
12356}
12357
[email protected]749eefa82010-09-13 22:14:0312358// Test for crbug.com/55424.
[email protected]23e482282013-06-14 16:08:0212359TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
[email protected]cdf8f7e72013-05-23 10:56:4612360 scoped_ptr<SpdyFrame> req(
bncce36dca22015-04-21 22:11:2312361 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rch8e6c6c42015-05-01 14:05:1312362 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]749eefa82010-09-13 22:14:0312363
[email protected]23e482282013-06-14 16:08:0212364 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12365 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0312366 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312367 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0312368 };
12369
rch8e6c6c42015-05-01 14:05:1312370 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
12371 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712372 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0312373
[email protected]8ddf8322012-02-23 18:08:0612374 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812375 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712376 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0312377
mmenkee65e7af2015-10-13 17:16:4212378 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0312379
12380 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2312381 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4012382 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5312383 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2712384 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:4212385 CreateInsecureSpdySession(session.get(), key, BoundNetLog());
[email protected]749eefa82010-09-13 22:14:0312386
12387 HttpRequestInfo request;
12388 request.method = "GET";
bncce36dca22015-04-21 22:11:2312389 request.url = GURL("https://www.example.org/");
[email protected]749eefa82010-09-13 22:14:0312390 request.load_flags = 0;
12391
12392 // This is the important line that marks this as a preconnect.
12393 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
12394
[email protected]262eec82013-03-19 21:01:3612395 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012396 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]749eefa82010-09-13 22:14:0312397
[email protected]41d64e82013-07-03 22:44:2612398 TestCompletionCallback callback;
[email protected]49639fa2011-12-20 23:22:4112399 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]749eefa82010-09-13 22:14:0312400 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112401 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]749eefa82010-09-13 22:14:0312402}
12403
[email protected]73b8dd222010-11-11 19:55:2412404// Given a net error, cause that error to be returned from the first Write()
12405// call and verify that the HttpTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0212406void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0712407 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2912408 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712409 request_info.url = GURL("https://www.example.com/");
12410 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912411 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712412
[email protected]8ddf8322012-02-23 18:08:0612413 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2912414 MockWrite data_writes[] = {
12415 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2412416 };
ttuttle859dc7a2015-04-23 19:42:2912417 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0712418 session_deps_.socket_factory->AddSocketDataProvider(&data);
12419 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2412420
mmenkee65e7af2015-10-13 17:16:4212421 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612422 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012423 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]73b8dd222010-11-11 19:55:2412424
[email protected]49639fa2011-12-20 23:22:4112425 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912426 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12427 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2412428 rv = callback.WaitForResult();
12429 ASSERT_EQ(error, rv);
12430}
12431
[email protected]23e482282013-06-14 16:08:0212432TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2412433 // Just check a grab bag of cert errors.
12434 static const int kErrors[] = {
12435 ERR_CERT_COMMON_NAME_INVALID,
12436 ERR_CERT_AUTHORITY_INVALID,
12437 ERR_CERT_DATE_INVALID,
12438 };
12439 for (size_t i = 0; i < arraysize(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0612440 CheckErrorIsPassedBack(kErrors[i], ASYNC);
12441 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2412442 }
12443}
12444
[email protected]bd0b6772011-01-11 19:59:3012445// Ensure that a client certificate is removed from the SSL client auth
12446// cache when:
12447// 1) No proxy is involved.
12448// 2) TLS False Start is disabled.
12449// 3) The initial TLS handshake requests a client certificate.
12450// 4) The client supplies an invalid/unacceptable certificate.
[email protected]23e482282013-06-14 16:08:0212451TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2312452 ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912453 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712454 request_info.url = GURL("https://www.example.com/");
12455 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912456 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712457
[email protected]bd0b6772011-01-11 19:59:3012458 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112459 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012460
12461 // [ssl_]data1 contains the data for the first SSL handshake. When a
12462 // CertificateRequest is received for the first time, the handshake will
12463 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2912464 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012465 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712466 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912467 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712468 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012469
12470 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
12471 // False Start is not being used, the result of the SSL handshake will be
12472 // returned as part of the SSLClientSocket::Connect() call. This test
12473 // matches the result of a server sending a handshake_failure alert,
12474 // rather than a Finished message, because it requires a client
12475 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2912476 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012477 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712478 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912479 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712480 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012481
12482 // [ssl_]data3 contains the data for the third SSL handshake. When a
12483 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212484 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
12485 // connection was attempted with TLSv1.2. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3012486 // of the HttpNetworkTransaction. Because this test failure is due to
12487 // requiring a client certificate, this fallback handshake should also
12488 // fail.
ttuttle859dc7a2015-04-23 19:42:2912489 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012490 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712491 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912492 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712493 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012494
[email protected]80c75f682012-05-26 16:22:1712495 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
12496 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212497 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
12498 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1712499 // of the HttpNetworkTransaction. Because this test failure is due to
12500 // requiring a client certificate, this fallback handshake should also
12501 // fail.
ttuttle859dc7a2015-04-23 19:42:2912502 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1712503 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712504 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912505 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712506 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712507
mmenkee65e7af2015-10-13 17:16:4212508 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612509 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012510 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012511
[email protected]bd0b6772011-01-11 19:59:3012512 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4112513 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912514 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12515 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012516
12517 // Complete the SSL handshake, which should abort due to requiring a
12518 // client certificate.
12519 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912520 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]bd0b6772011-01-11 19:59:3012521
12522 // Indicate that no certificate should be supplied. From the perspective
12523 // of SSLClientCertCache, NULL is just as meaningful as a real
12524 // certificate, so this is the same as supply a
12525 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412526 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912527 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012528
12529 // Ensure the certificate was added to the client auth cache before
12530 // allowing the connection to continue restarting.
12531 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412532 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112533 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412534 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012535 ASSERT_EQ(NULL, client_cert.get());
12536
12537 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712538 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12539 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012540 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912541 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
[email protected]bd0b6772011-01-11 19:59:3012542
12543 // Ensure that the client certificate is removed from the cache on a
12544 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112545 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412546 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012547}
12548
12549// Ensure that a client certificate is removed from the SSL client auth
12550// cache when:
12551// 1) No proxy is involved.
12552// 2) TLS False Start is enabled.
12553// 3) The initial TLS handshake requests a client certificate.
12554// 4) The client supplies an invalid/unacceptable certificate.
[email protected]23e482282013-06-14 16:08:0212555TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2312556 ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912557 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712558 request_info.url = GURL("https://www.example.com/");
12559 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912560 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712561
[email protected]bd0b6772011-01-11 19:59:3012562 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112563 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012564
12565 // When TLS False Start is used, SSLClientSocket::Connect() calls will
12566 // return successfully after reading up to the peer's Certificate message.
12567 // This is to allow the caller to call SSLClientSocket::Write(), which can
12568 // enqueue application data to be sent in the same packet as the
12569 // ChangeCipherSpec and Finished messages.
12570 // The actual handshake will be finished when SSLClientSocket::Read() is
12571 // called, which expects to process the peer's ChangeCipherSpec and
12572 // Finished messages. If there was an error negotiating with the peer,
12573 // such as due to the peer requiring a client certificate when none was
12574 // supplied, the alert sent by the peer won't be processed until Read() is
12575 // called.
12576
12577 // Like the non-False Start case, when a client certificate is requested by
12578 // the peer, the handshake is aborted during the Connect() call.
12579 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2912580 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012581 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712582 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912583 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712584 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012585
12586 // When a client certificate is supplied, Connect() will not be aborted
12587 // when the peer requests the certificate. Instead, the handshake will
12588 // artificially succeed, allowing the caller to write the HTTP request to
12589 // the socket. The handshake messages are not processed until Read() is
12590 // called, which then detects that the handshake was aborted, due to the
12591 // peer sending a handshake_failure because it requires a client
12592 // certificate.
ttuttle859dc7a2015-04-23 19:42:2912593 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012594 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712595 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912596 MockRead data2_reads[] = {
12597 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3012598 };
ttuttle859dc7a2015-04-23 19:42:2912599 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712600 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012601
12602 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1712603 // the data for the SSL handshake once the TLSv1.1 connection falls back to
12604 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912605 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012606 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712607 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912608 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712609 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012610
[email protected]80c75f682012-05-26 16:22:1712611 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
12612 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912613 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1712614 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712615 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912616 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712617 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712618
[email protected]7799de12013-05-30 05:52:5112619 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2912620 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5112621 ssl_data5.cert_request_info = cert_request.get();
12622 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
ttuttle859dc7a2015-04-23 19:42:2912623 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]7799de12013-05-30 05:52:5112624 session_deps_.socket_factory->AddSocketDataProvider(&data5);
12625
mmenkee65e7af2015-10-13 17:16:4212626 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612627 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012628 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012629
[email protected]bd0b6772011-01-11 19:59:3012630 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4112631 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912632 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12633 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012634
12635 // Complete the SSL handshake, which should abort due to requiring a
12636 // client certificate.
12637 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912638 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]bd0b6772011-01-11 19:59:3012639
12640 // Indicate that no certificate should be supplied. From the perspective
12641 // of SSLClientCertCache, NULL is just as meaningful as a real
12642 // certificate, so this is the same as supply a
12643 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412644 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912645 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012646
12647 // Ensure the certificate was added to the client auth cache before
12648 // allowing the connection to continue restarting.
12649 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412650 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112651 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412652 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012653 ASSERT_EQ(NULL, client_cert.get());
12654
[email protected]bd0b6772011-01-11 19:59:3012655 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712656 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12657 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012658 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912659 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
[email protected]bd0b6772011-01-11 19:59:3012660
12661 // Ensure that the client certificate is removed from the cache on a
12662 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112663 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412664 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012665}
12666
[email protected]8c405132011-01-11 22:03:1812667// Ensure that a client certificate is removed from the SSL client auth
12668// cache when:
12669// 1) An HTTPS proxy is involved.
12670// 3) The HTTPS proxy requests a client certificate.
12671// 4) The client supplies an invalid/unacceptable certificate for the
12672// proxy.
12673// The test is repeated twice, first for connecting to an HTTPS endpoint,
12674// then for connecting to an HTTP endpoint.
[email protected]23e482282013-06-14 16:08:0212675TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
rdsmith82957ad2015-09-16 19:42:0312676 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:5112677 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712678 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1812679
12680 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112681 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1812682
12683 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
12684 // [ssl_]data[1-3]. Rather than represending the endpoint
12685 // (www.example.com:443), they represent failures with the HTTPS proxy
12686 // (proxy:70).
ttuttle859dc7a2015-04-23 19:42:2912687 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8c405132011-01-11 22:03:1812688 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712689 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912690 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712691 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1812692
ttuttle859dc7a2015-04-23 19:42:2912693 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812694 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712695 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912696 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712697 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8c405132011-01-11 22:03:1812698
[email protected]80c75f682012-05-26 16:22:1712699 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
12700#if 0
ttuttle859dc7a2015-04-23 19:42:2912701 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812702 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712703 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912704 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712705 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]80c75f682012-05-26 16:22:1712706#endif
[email protected]8c405132011-01-11 22:03:1812707
ttuttle859dc7a2015-04-23 19:42:2912708 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1812709 requests[0].url = GURL("https://www.example.com/");
12710 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912711 requests[0].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812712
12713 requests[1].url = GURL("http://www.example.com/");
12714 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912715 requests[1].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812716
12717 for (size_t i = 0; i < arraysize(requests); ++i) {
[email protected]bb88e1d32013-05-03 23:11:0712718 session_deps_.socket_factory->ResetNextMockIndexes();
mmenkee65e7af2015-10-13 17:16:4212719 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c405132011-01-11 22:03:1812720 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5012721 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c405132011-01-11 22:03:1812722
12723 // Begin the SSL handshake with the proxy.
[email protected]49639fa2011-12-20 23:22:4112724 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912725 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
12726 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]8c405132011-01-11 22:03:1812727
12728 // Complete the SSL handshake, which should abort due to requiring a
12729 // client certificate.
12730 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912731 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]8c405132011-01-11 22:03:1812732
12733 // Indicate that no certificate should be supplied. From the perspective
12734 // of SSLClientCertCache, NULL is just as meaningful as a real
12735 // certificate, so this is the same as supply a
12736 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412737 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912738 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]8c405132011-01-11 22:03:1812739
12740 // Ensure the certificate was added to the client auth cache before
12741 // allowing the connection to continue restarting.
12742 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412743 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112744 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412745 HostPortPair("proxy", 70), &client_cert, &client_private_key));
[email protected]8c405132011-01-11 22:03:1812746 ASSERT_EQ(NULL, client_cert.get());
12747 // Ensure the certificate was NOT cached for the endpoint. This only
12748 // applies to HTTPS requests, but is fine to check for HTTP requests.
[email protected]791879c2013-12-17 07:22:4112749 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412750 HostPortPair("www.example.com", 443), &client_cert,
12751 &client_private_key));
[email protected]8c405132011-01-11 22:03:1812752
12753 // Restart the handshake. This will consume ssl_data2, which fails, and
12754 // then consume ssl_data3, which should also fail. The result code is
12755 // checked against what ssl_data3 should return.
12756 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912757 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]8c405132011-01-11 22:03:1812758
12759 // Now that the new handshake has failed, ensure that the client
12760 // certificate was removed from the client auth cache.
[email protected]791879c2013-12-17 07:22:4112761 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412762 HostPortPair("proxy", 70), &client_cert, &client_private_key));
[email protected]791879c2013-12-17 07:22:4112763 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412764 HostPortPair("www.example.com", 443), &client_cert,
12765 &client_private_key));
[email protected]8c405132011-01-11 22:03:1812766 }
12767}
12768
mmenke5c642132015-06-02 16:05:1312769TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
bnc55ff9da2015-08-19 18:42:3512770 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312771 session_deps_.next_protos = SpdyNextProtos();
[email protected]e3ceb682011-06-28 23:55:4612772
12773 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712774 session_deps_.host_resolver.reset(new MockCachingHostResolver());
mmenkee65e7af2015-10-13 17:16:4212775 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2612776 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12777 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4612778
[email protected]8ddf8322012-02-23 18:08:0612779 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812780 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712781 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4612782
[email protected]cdf8f7e72013-05-23 10:56:4612783 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2312784 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812785 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4612786 scoped_ptr<SpdyFrame> host2_req(
12787 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4612788 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312789 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4612790 };
[email protected]23e482282013-06-14 16:08:0212791 scoped_ptr<SpdyFrame> host1_resp(
12792 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12793 scoped_ptr<SpdyFrame> host1_resp_body(
12794 spdy_util_.ConstructSpdyBodyFrame(1, true));
12795 scoped_ptr<SpdyFrame> host2_resp(
12796 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12797 scoped_ptr<SpdyFrame> host2_resp_body(
12798 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4612799 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312800 CreateMockRead(*host1_resp, 1),
12801 CreateMockRead(*host1_resp_body, 2),
12802 CreateMockRead(*host2_resp, 4),
12803 CreateMockRead(*host2_resp_body, 5),
12804 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4612805 };
12806
[email protected]d2b5f092012-06-08 23:55:0212807 IPAddressNumber ip;
12808 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
12809 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12810 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312811 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12812 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712813 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4612814
[email protected]aa22b242011-11-16 18:58:2912815 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4612816 HttpRequestInfo request1;
12817 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312818 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4612819 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012820 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612821
[email protected]49639fa2011-12-20 23:22:4112822 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612823 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112824 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612825
12826 const HttpResponseInfo* response = trans1.GetResponseInfo();
12827 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012828 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212829 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612830
12831 std::string response_data;
12832 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12833 EXPECT_EQ("hello!", response_data);
12834
12835 // Preload www.gmail.com into HostCache.
12836 HostPortPair host_port("www.gmail.com", 443);
[email protected]5109c1952013-08-20 18:44:1012837 HostResolver::RequestInfo resolve_info(host_port);
[email protected]e3ceb682011-06-28 23:55:4612838 AddressList ignored;
[email protected]5109c1952013-08-20 18:44:1012839 rv = session_deps_.host_resolver->Resolve(resolve_info,
12840 DEFAULT_PRIORITY,
12841 &ignored,
12842 callback.callback(),
12843 NULL,
12844 BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:4712845 EXPECT_EQ(ERR_IO_PENDING, rv);
12846 rv = callback.WaitForResult();
12847 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:4612848
12849 HttpRequestInfo request2;
12850 request2.method = "GET";
12851 request2.url = GURL("https://www.gmail.com/");
12852 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012853 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612854
[email protected]49639fa2011-12-20 23:22:4112855 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612856 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112857 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612858
12859 response = trans2.GetResponseInfo();
12860 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012861 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212862 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612863 EXPECT_TRUE(response->was_fetched_via_spdy);
12864 EXPECT_TRUE(response->was_npn_negotiated);
12865 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12866 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4612867}
12868
[email protected]23e482282013-06-14 16:08:0212869TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
bnc55ff9da2015-08-19 18:42:3512870 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312871 session_deps_.next_protos = SpdyNextProtos();
[email protected]d2b5f092012-06-08 23:55:0212872
12873 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712874 session_deps_.host_resolver.reset(new MockCachingHostResolver());
mmenkee65e7af2015-10-13 17:16:4212875 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0212876 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12877 pool_peer.DisableDomainAuthenticationVerification();
12878
12879 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812880 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712881 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]d2b5f092012-06-08 23:55:0212882
[email protected]cdf8f7e72013-05-23 10:56:4612883 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2312884 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812885 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4612886 scoped_ptr<SpdyFrame> host2_req(
12887 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0212888 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312889 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0212890 };
[email protected]23e482282013-06-14 16:08:0212891 scoped_ptr<SpdyFrame> host1_resp(
12892 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12893 scoped_ptr<SpdyFrame> host1_resp_body(
12894 spdy_util_.ConstructSpdyBodyFrame(1, true));
12895 scoped_ptr<SpdyFrame> host2_resp(
12896 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12897 scoped_ptr<SpdyFrame> host2_resp_body(
12898 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0212899 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312900 CreateMockRead(*host1_resp, 1),
12901 CreateMockRead(*host1_resp_body, 2),
12902 CreateMockRead(*host2_resp, 4),
12903 CreateMockRead(*host2_resp_body, 5),
12904 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0212905 };
12906
12907 IPAddressNumber ip;
12908 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
12909 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12910 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312911 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12912 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712913 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0212914
12915 TestCompletionCallback callback;
12916 HttpRequestInfo request1;
12917 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312918 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0212919 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012920 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0212921
12922 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
12923 EXPECT_EQ(ERR_IO_PENDING, rv);
12924 EXPECT_EQ(OK, callback.WaitForResult());
12925
12926 const HttpResponseInfo* response = trans1.GetResponseInfo();
12927 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012928 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212929 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0212930
12931 std::string response_data;
12932 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12933 EXPECT_EQ("hello!", response_data);
12934
12935 HttpRequestInfo request2;
12936 request2.method = "GET";
12937 request2.url = GURL("https://www.gmail.com/");
12938 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012939 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0212940
12941 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
12942 EXPECT_EQ(ERR_IO_PENDING, rv);
12943 EXPECT_EQ(OK, callback.WaitForResult());
12944
12945 response = trans2.GetResponseInfo();
12946 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012947 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212948 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0212949 EXPECT_TRUE(response->was_fetched_via_spdy);
12950 EXPECT_TRUE(response->was_npn_negotiated);
12951 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12952 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0212953}
12954
ttuttle859dc7a2015-04-23 19:42:2912955class OneTimeCachingHostResolver : public HostResolver {
[email protected]e3ceb682011-06-28 23:55:4612956 public:
12957 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
12958 : host_port_(host_port) {}
dchengb03027d2014-10-21 12:00:2012959 ~OneTimeCachingHostResolver() override {}
[email protected]e3ceb682011-06-28 23:55:4612960
12961 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
12962
12963 // HostResolver methods:
dchengb03027d2014-10-21 12:00:2012964 int Resolve(const RequestInfo& info,
12965 RequestPriority priority,
12966 AddressList* addresses,
12967 const CompletionCallback& callback,
12968 RequestHandle* out_req,
12969 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4012970 return host_resolver_.Resolve(
[email protected]5109c1952013-08-20 18:44:1012971 info, priority, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:4012972 }
12973
dchengb03027d2014-10-21 12:00:2012974 int ResolveFromCache(const RequestInfo& info,
12975 AddressList* addresses,
12976 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4012977 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
12978 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]98e1cd012011-11-08 15:33:0912979 host_resolver_.GetHostCache()->clear();
[email protected]e3ceb682011-06-28 23:55:4612980 return rv;
12981 }
12982
dchengb03027d2014-10-21 12:00:2012983 void CancelRequest(RequestHandle req) override {
[email protected]e3ceb682011-06-28 23:55:4612984 host_resolver_.CancelRequest(req);
12985 }
12986
[email protected]46da33be2011-07-19 21:58:0412987 MockCachingHostResolver* GetMockHostResolver() {
12988 return &host_resolver_;
12989 }
12990
[email protected]e3ceb682011-06-28 23:55:4612991 private:
12992 MockCachingHostResolver host_resolver_;
12993 const HostPortPair host_port_;
12994};
12995
mmenke5c642132015-06-02 16:05:1312996TEST_P(HttpNetworkTransactionTest,
12997 UseIPConnectionPoolingWithHostCacheExpiration) {
bnc55ff9da2015-08-19 18:42:3512998 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312999 session_deps_.next_protos = SpdyNextProtos();
[email protected]e3ceb682011-06-28 23:55:4613000
13001 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
[email protected]e3ceb682011-06-28 23:55:4613002 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
[email protected]c6bf8152012-12-02 07:43:3413003 HttpNetworkSession::Params params =
[email protected]bb88e1d32013-05-03 23:11:0713004 SpdySessionDependencies::CreateSessionParams(&session_deps_);
[email protected]e3ceb682011-06-28 23:55:4613005 params.host_resolver = &host_resolver;
mmenkee65e7af2015-10-13 17:16:4213006 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2613007 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
13008 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4613009
[email protected]8ddf8322012-02-23 18:08:0613010 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813011 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713012 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4613013
[email protected]cdf8f7e72013-05-23 10:56:4613014 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2313015 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3813016 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4613017 scoped_ptr<SpdyFrame> host2_req(
13018 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4613019 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1313020 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4613021 };
[email protected]23e482282013-06-14 16:08:0213022 scoped_ptr<SpdyFrame> host1_resp(
13023 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13024 scoped_ptr<SpdyFrame> host1_resp_body(
13025 spdy_util_.ConstructSpdyBodyFrame(1, true));
13026 scoped_ptr<SpdyFrame> host2_resp(
13027 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13028 scoped_ptr<SpdyFrame> host2_resp_body(
13029 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4613030 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1313031 CreateMockRead(*host1_resp, 1),
13032 CreateMockRead(*host1_resp_body, 2),
13033 CreateMockRead(*host2_resp, 4),
13034 CreateMockRead(*host2_resp_body, 5),
13035 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4613036 };
13037
[email protected]d2b5f092012-06-08 23:55:0213038 IPAddressNumber ip;
13039 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
13040 IPEndPoint peer_addr = IPEndPoint(ip, 443);
13041 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1313042 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
13043 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0713044 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4613045
[email protected]aa22b242011-11-16 18:58:2913046 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4613047 HttpRequestInfo request1;
13048 request1.method = "GET";
bncce36dca22015-04-21 22:11:2313049 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4613050 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013051 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4613052
[email protected]49639fa2011-12-20 23:22:4113053 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4613054 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4113055 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4613056
13057 const HttpResponseInfo* response = trans1.GetResponseInfo();
13058 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013059 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0213060 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4613061
13062 std::string response_data;
13063 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
13064 EXPECT_EQ("hello!", response_data);
13065
13066 // Preload cache entries into HostCache.
[email protected]5109c1952013-08-20 18:44:1013067 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
[email protected]e3ceb682011-06-28 23:55:4613068 AddressList ignored;
[email protected]5109c1952013-08-20 18:44:1013069 rv = host_resolver.Resolve(resolve_info,
13070 DEFAULT_PRIORITY,
13071 &ignored,
13072 callback.callback(),
13073 NULL,
13074 BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:4713075 EXPECT_EQ(ERR_IO_PENDING, rv);
13076 rv = callback.WaitForResult();
13077 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:4613078
13079 HttpRequestInfo request2;
13080 request2.method = "GET";
13081 request2.url = GURL("https://www.gmail.com/");
13082 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013083 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4613084
[email protected]49639fa2011-12-20 23:22:4113085 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4613086 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4113087 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4613088
13089 response = trans2.GetResponseInfo();
13090 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013091 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0213092 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4613093 EXPECT_TRUE(response->was_fetched_via_spdy);
13094 EXPECT_TRUE(response->was_npn_negotiated);
13095 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
13096 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4613097}
13098
[email protected]23e482282013-06-14 16:08:0213099TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2313100 const std::string https_url = "https://www.example.org:8080/";
13101 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0413102
13103 // SPDY GET for HTTPS URL
[email protected]cdf8f7e72013-05-23 10:56:4613104 scoped_ptr<SpdyFrame> req1(
13105 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0413106
13107 MockWrite writes1[] = {
13108 CreateMockWrite(*req1, 0),
13109 };
13110
[email protected]23e482282013-06-14 16:08:0213111 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13112 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]8450d722012-07-02 19:14:0413113 MockRead reads1[] = {
13114 CreateMockRead(*resp1, 1),
13115 CreateMockRead(*body1, 2),
13116 MockRead(ASYNC, ERR_IO_PENDING, 3)
13117 };
13118
rch8e6c6c42015-05-01 14:05:1313119 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
13120 arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0413121 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5713122 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0413123
13124 // HTTP GET for the HTTP URL
13125 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1313126 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3413127 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2313128 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3413129 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0413130 };
13131
13132 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1313133 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
13134 MockRead(ASYNC, 2, "hello"),
13135 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0413136 };
13137
rch8e6c6c42015-05-01 14:05:1313138 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13139 arraysize(writes2));
[email protected]8450d722012-07-02 19:14:0413140
[email protected]8450d722012-07-02 19:14:0413141 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813142 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713143 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13144 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13145 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0413146
mmenkee65e7af2015-10-13 17:16:4213147 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0413148
13149 // Start the first transaction to set up the SpdySession
13150 HttpRequestInfo request1;
13151 request1.method = "GET";
13152 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0413153 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013154 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0413155 TestCompletionCallback callback1;
13156 EXPECT_EQ(ERR_IO_PENDING,
13157 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413158 base::MessageLoop::current()->RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0413159
13160 EXPECT_EQ(OK, callback1.WaitForResult());
13161 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13162
13163 // Now, start the HTTP request
13164 HttpRequestInfo request2;
13165 request2.method = "GET";
13166 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0413167 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013168 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0413169 TestCompletionCallback callback2;
13170 EXPECT_EQ(ERR_IO_PENDING,
13171 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413172 base::MessageLoop::current()->RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0413173
13174 EXPECT_EQ(OK, callback2.WaitForResult());
13175 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13176}
13177
bnc1b0e36852015-04-28 15:32:5913178class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
13179 public:
13180 void Run(bool pooling, bool valid) {
13181 HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org",
13182 443);
13183 HostPortPair alternative("www.example.org", 443);
13184
13185 base::FilePath certs_dir = GetTestCertsDirectory();
13186 scoped_refptr<X509Certificate> cert(
13187 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
13188 ASSERT_TRUE(cert.get());
13189 bool common_name_fallback_used;
13190 EXPECT_EQ(valid,
13191 cert->VerifyNameMatch(origin.host(), &common_name_fallback_used));
13192 EXPECT_TRUE(
13193 cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used));
13194 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813195 ssl.SetNextProto(GetProtocol());
bnc1b0e36852015-04-28 15:32:5913196 ssl.cert = cert;
13197 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13198
13199 // If pooling, then start a request to alternative first to create a
13200 // SpdySession.
13201 std::string url0 = "https://www.example.org:443";
13202 // Second request to origin, which has an alternative service, and could
13203 // open a connection to the alternative host or pool to the existing one.
13204 std::string url1("https://");
13205 url1.append(origin.host());
13206 url1.append(":443");
13207
13208 scoped_ptr<SpdyFrame> req0;
13209 scoped_ptr<SpdyFrame> req1;
13210 scoped_ptr<SpdyFrame> resp0;
13211 scoped_ptr<SpdyFrame> body0;
13212 scoped_ptr<SpdyFrame> resp1;
13213 scoped_ptr<SpdyFrame> body1;
13214 std::vector<MockWrite> writes;
13215 std::vector<MockRead> reads;
13216
13217 if (pooling) {
13218 req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3813219 spdy_util_.UpdateWithStreamDestruction(1);
bnc1b0e36852015-04-28 15:32:5913220 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 3, LOWEST));
13221
13222 writes.push_back(CreateMockWrite(*req0, 0));
13223 writes.push_back(CreateMockWrite(*req1, 3));
13224
13225 resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13226 body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
13227 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13228 body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true));
13229
13230 reads.push_back(CreateMockRead(*resp0, 1));
13231 reads.push_back(CreateMockRead(*body0, 2));
13232 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4));
13233 reads.push_back(CreateMockRead(*resp1, 5));
13234 reads.push_back(CreateMockRead(*body1, 6));
13235 reads.push_back(MockRead(ASYNC, OK, 7));
13236 } else {
13237 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 1, LOWEST));
13238
13239 writes.push_back(CreateMockWrite(*req1, 0));
13240
13241 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13242 body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
13243
13244 reads.push_back(CreateMockRead(*resp1, 1));
13245 reads.push_back(CreateMockRead(*body1, 2));
13246 reads.push_back(MockRead(ASYNC, OK, 3));
13247 }
13248
davidben5f8b6bc2015-11-25 03:19:5413249 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
13250 writes.size());
bnc1b0e36852015-04-28 15:32:5913251 session_deps_.socket_factory->AddSocketDataProvider(&data);
13252
13253 // Connection to the origin fails.
13254 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13255 StaticSocketDataProvider data_refused;
13256 data_refused.set_connect_data(mock_connect);
13257 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13258
bnc55ff9da2015-08-19 18:42:3513259 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213260 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc1b0e36852015-04-28 15:32:5913261 base::WeakPtr<HttpServerProperties> http_server_properties =
13262 session->http_server_properties();
13263 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813264 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213265 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc1b0e36852015-04-28 15:32:5913266 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213267 1.0, expiration);
bnc1b0e36852015-04-28 15:32:5913268
13269 // First request to alternative.
13270 if (pooling) {
13271 scoped_ptr<HttpTransaction> trans0(
13272 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13273 HttpRequestInfo request0;
13274 request0.method = "GET";
13275 request0.url = GURL(url0);
13276 request0.load_flags = 0;
13277 TestCompletionCallback callback0;
13278
13279 int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog());
13280 EXPECT_EQ(ERR_IO_PENDING, rv);
13281 rv = callback0.WaitForResult();
13282 EXPECT_EQ(OK, rv);
13283 }
13284
13285 // Second request to origin.
13286 scoped_ptr<HttpTransaction> trans1(
13287 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13288 HttpRequestInfo request1;
13289 request1.method = "GET";
13290 request1.url = GURL(url1);
13291 request1.load_flags = 0;
13292 TestCompletionCallback callback1;
13293
13294 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
13295 EXPECT_EQ(ERR_IO_PENDING, rv);
rch32320842015-05-16 15:57:0913296 base::MessageLoop::current()->RunUntilIdle();
13297 if (data.IsReadPaused()) {
13298 data.CompleteRead();
13299 }
bnc1b0e36852015-04-28 15:32:5913300 rv = callback1.WaitForResult();
13301 if (valid) {
13302 EXPECT_EQ(OK, rv);
13303 } else {
13304 if (pooling) {
13305 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
13306 } else {
13307 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv);
13308 }
13309 }
13310 }
13311};
13312
rdsmithebb50aa2015-11-12 03:44:3813313INSTANTIATE_TEST_CASE_P(ProtoPlusDepend,
bnc1b0e36852015-04-28 15:32:5913314 AltSvcCertificateVerificationTest,
rdsmithebb50aa2015-11-12 03:44:3813315 testing::Values(kTestCaseSPDY31,
13316 kTestCaseHTTP2NoPriorityDependencies,
13317 kTestCaseHTTP2PriorityDependencies));
bnc1b0e36852015-04-28 15:32:5913318
13319// The alternative service host must exhibit a certificate that is valid for the
13320// origin host. Test that this is enforced when pooling to an existing
13321// connection.
13322TEST_P(AltSvcCertificateVerificationTest, PoolingValid) {
13323 Run(true, true);
13324}
13325
13326TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) {
13327 Run(true, false);
13328}
13329
13330// The alternative service host must exhibit a certificate that is valid for the
13331// origin host. Test that this is enforced when opening a new connection.
13332TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) {
13333 Run(false, true);
13334}
13335
13336TEST_P(AltSvcCertificateVerificationTest, NewConnectionInvalid) {
13337 Run(false, false);
13338}
13339
bnc5452e2a2015-05-08 16:27:4213340// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
13341// with the alternative server. That connection should not be used.
13342TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
13343 HostPortPair origin("origin.example.org", 443);
13344 HostPortPair alternative("alternative.example.org", 443);
13345
13346 // Negotiate HTTP/1.1 with alternative.example.org.
13347 SSLSocketDataProvider ssl(ASYNC, OK);
13348 ssl.SetNextProto(kProtoHTTP11);
13349 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13350
13351 // No data should be read from the alternative, because HTTP/1.1 is
13352 // negotiated.
13353 StaticSocketDataProvider data;
13354 session_deps_.socket_factory->AddSocketDataProvider(&data);
13355
13356 // This test documents that an alternate Job should not be used if HTTP/1.1 is
13357 // negotiated. In order to test this, a failed connection to the origin is
13358 // mocked. This way the request relies on the alternate Job.
13359 StaticSocketDataProvider data_refused;
13360 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13361 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13362
13363 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3513364 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213365 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc5452e2a2015-05-08 16:27:4213366 base::WeakPtr<HttpServerProperties> http_server_properties =
13367 session->http_server_properties();
13368 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813369 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213370 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc5452e2a2015-05-08 16:27:4213371 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213372 1.0, expiration);
bnc5452e2a2015-05-08 16:27:4213373
13374 scoped_ptr<HttpTransaction> trans(
13375 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13376 HttpRequestInfo request;
13377 request.method = "GET";
13378 request.url = GURL("https://origin.example.org:443");
13379 request.load_flags = 0;
13380 TestCompletionCallback callback;
13381
13382 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
13383 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
13384 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13385 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED, callback.GetResult(rv));
13386}
13387
bnc40448a532015-05-11 19:13:1413388// A request to a server with an alternative service fires two Jobs: one to the
13389// origin, and an alternate one to the alternative server. If the former
13390// succeeds, the request should succeed, even if the latter fails because
13391// HTTP/1.1 is negotiated which is insufficient for alternative service.
13392TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
13393 HostPortPair origin("origin.example.org", 443);
13394 HostPortPair alternative("alternative.example.org", 443);
13395
13396 // Negotiate HTTP/1.1 with alternative.
13397 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
13398 alternative_ssl.SetNextProto(kProtoHTTP11);
13399 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
13400
13401 // No data should be read from the alternative, because HTTP/1.1 is
13402 // negotiated.
13403 StaticSocketDataProvider data;
13404 session_deps_.socket_factory->AddSocketDataProvider(&data);
13405
13406 // Negotiate HTTP/1.1 with origin.
13407 SSLSocketDataProvider origin_ssl(ASYNC, OK);
13408 origin_ssl.SetNextProto(kProtoHTTP11);
13409 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
13410
13411 MockWrite http_writes[] = {
13412 MockWrite(
13413 "GET / HTTP/1.1\r\n"
13414 "Host: origin.example.org\r\n"
13415 "Connection: keep-alive\r\n\r\n"),
13416 MockWrite(
13417 "GET /second HTTP/1.1\r\n"
13418 "Host: origin.example.org\r\n"
13419 "Connection: keep-alive\r\n\r\n"),
13420 };
13421
13422 MockRead http_reads[] = {
13423 MockRead("HTTP/1.1 200 OK\r\n"),
13424 MockRead("Content-Type: text/html\r\n"),
13425 MockRead("Content-Length: 6\r\n\r\n"),
13426 MockRead("foobar"),
13427 MockRead("HTTP/1.1 200 OK\r\n"),
13428 MockRead("Content-Type: text/html\r\n"),
13429 MockRead("Content-Length: 7\r\n\r\n"),
13430 MockRead("another"),
13431 };
13432 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13433 http_writes, arraysize(http_writes));
13434 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13435
13436 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3513437 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213438 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc40448a532015-05-11 19:13:1413439 base::WeakPtr<HttpServerProperties> http_server_properties =
13440 session->http_server_properties();
13441 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813442 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213443 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc40448a532015-05-11 19:13:1413444 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213445 1.0, expiration);
bnc40448a532015-05-11 19:13:1413446
13447 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
13448 HttpRequestInfo request1;
13449 request1.method = "GET";
13450 request1.url = GURL("https://origin.example.org:443");
13451 request1.load_flags = 0;
13452 TestCompletionCallback callback1;
13453
13454 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
13455 rv = callback1.GetResult(rv);
13456 EXPECT_EQ(OK, rv);
13457
13458 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
13459 ASSERT_TRUE(response1 != nullptr);
13460 ASSERT_TRUE(response1->headers.get() != nullptr);
13461 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13462
13463 std::string response_data1;
13464 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data1));
13465 EXPECT_EQ("foobar", response_data1);
13466
13467 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
13468 // for alternative service.
13469 EXPECT_TRUE(
13470 http_server_properties->IsAlternativeServiceBroken(alternative_service));
13471
13472 // Since |alternative_service| is broken, a second transaction to origin
13473 // should not start an alternate Job. It should pool to existing connection
13474 // to origin.
13475 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
13476 HttpRequestInfo request2;
13477 request2.method = "GET";
13478 request2.url = GURL("https://origin.example.org:443/second");
13479 request2.load_flags = 0;
13480 TestCompletionCallback callback2;
13481
13482 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
13483 rv = callback2.GetResult(rv);
13484 EXPECT_EQ(OK, rv);
13485
13486 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
13487 ASSERT_TRUE(response2 != nullptr);
13488 ASSERT_TRUE(response2->headers.get() != nullptr);
13489 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
13490
13491 std::string response_data2;
13492 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data2));
13493 EXPECT_EQ("another", response_data2);
13494}
13495
bnc5452e2a2015-05-08 16:27:4213496// Alternative service requires HTTP/2 (or SPDY), but there is already a
13497// HTTP/1.1 socket open to the alternative server. That socket should not be
13498// used.
13499TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
13500 HostPortPair origin("origin.example.org", 443);
13501 HostPortPair alternative("alternative.example.org", 443);
13502 std::string origin_url = "https://origin.example.org:443";
13503 std::string alternative_url = "https://alternative.example.org:443";
13504
13505 // Negotiate HTTP/1.1 with alternative.example.org.
13506 SSLSocketDataProvider ssl(ASYNC, OK);
13507 ssl.SetNextProto(kProtoHTTP11);
13508 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13509
13510 // HTTP/1.1 data for |request1| and |request2|.
13511 MockWrite http_writes[] = {
13512 MockWrite(
13513 "GET / HTTP/1.1\r\n"
13514 "Host: alternative.example.org\r\n"
13515 "Connection: keep-alive\r\n\r\n"),
13516 MockWrite(
13517 "GET / HTTP/1.1\r\n"
13518 "Host: alternative.example.org\r\n"
13519 "Connection: keep-alive\r\n\r\n"),
13520 };
13521
13522 MockRead http_reads[] = {
13523 MockRead(
13524 "HTTP/1.1 200 OK\r\n"
13525 "Content-Type: text/html; charset=iso-8859-1\r\n"
13526 "Content-Length: 40\r\n\r\n"
13527 "first HTTP/1.1 response from alternative"),
13528 MockRead(
13529 "HTTP/1.1 200 OK\r\n"
13530 "Content-Type: text/html; charset=iso-8859-1\r\n"
13531 "Content-Length: 41\r\n\r\n"
13532 "second HTTP/1.1 response from alternative"),
13533 };
13534 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13535 http_writes, arraysize(http_writes));
13536 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13537
13538 // This test documents that an alternate Job should not pool to an already
13539 // existing HTTP/1.1 connection. In order to test this, a failed connection
13540 // to the origin is mocked. This way |request2| relies on the alternate Job.
13541 StaticSocketDataProvider data_refused;
13542 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13543 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13544
13545 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3513546 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213547 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc5452e2a2015-05-08 16:27:4213548 base::WeakPtr<HttpServerProperties> http_server_properties =
13549 session->http_server_properties();
13550 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813551 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213552 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc5452e2a2015-05-08 16:27:4213553 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213554 1.0, expiration);
bnc5452e2a2015-05-08 16:27:4213555
13556 // First transaction to alternative to open an HTTP/1.1 socket.
13557 scoped_ptr<HttpTransaction> trans1(
13558 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13559 HttpRequestInfo request1;
13560 request1.method = "GET";
13561 request1.url = GURL(alternative_url);
13562 request1.load_flags = 0;
13563 TestCompletionCallback callback1;
13564
13565 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
13566 EXPECT_EQ(OK, callback1.GetResult(rv));
13567 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
13568 ASSERT_TRUE(response1);
13569 ASSERT_TRUE(response1->headers.get());
13570 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13571 EXPECT_TRUE(response1->was_npn_negotiated);
13572 EXPECT_FALSE(response1->was_fetched_via_spdy);
13573 std::string response_data1;
13574 ASSERT_EQ(OK, ReadTransaction(trans1.get(), &response_data1));
13575 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
13576
13577 // Request for origin.example.org, which has an alternative service. This
13578 // will start two Jobs: the alternative looks for connections to pool to,
13579 // finds one which is HTTP/1.1, and should ignore it, and should not try to
13580 // open other connections to alternative server. The Job to origin fails, so
13581 // this request fails.
13582 scoped_ptr<HttpTransaction> trans2(
13583 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13584 HttpRequestInfo request2;
13585 request2.method = "GET";
13586 request2.url = GURL(origin_url);
13587 request2.load_flags = 0;
13588 TestCompletionCallback callback2;
13589
13590 rv = trans2->Start(&request2, callback2.callback(), BoundNetLog());
13591 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback2.GetResult(rv));
13592
13593 // Another transaction to alternative. This is to test that the HTTP/1.1
13594 // socket is still open and in the pool.
13595 scoped_ptr<HttpTransaction> trans3(
13596 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13597 HttpRequestInfo request3;
13598 request3.method = "GET";
13599 request3.url = GURL(alternative_url);
13600 request3.load_flags = 0;
13601 TestCompletionCallback callback3;
13602
13603 rv = trans3->Start(&request3, callback3.callback(), BoundNetLog());
13604 EXPECT_EQ(OK, callback3.GetResult(rv));
13605 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
13606 ASSERT_TRUE(response3);
13607 ASSERT_TRUE(response3->headers.get());
13608 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
13609 EXPECT_TRUE(response3->was_npn_negotiated);
13610 EXPECT_FALSE(response3->was_fetched_via_spdy);
13611 std::string response_data3;
13612 ASSERT_EQ(OK, ReadTransaction(trans3.get(), &response_data3));
13613 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
13614}
13615
[email protected]23e482282013-06-14 16:08:0213616TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2313617 const std::string https_url = "https://www.example.org:8080/";
13618 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0413619
rdsmithebb50aa2015-11-12 03:44:3813620 // Separate SPDY util instance for naked and wrapped requests.
13621 SpdyTestUtil spdy_util_wrapped(GetProtocol(), GetDependenciesFromPriority());
13622
[email protected]8450d722012-07-02 19:14:0413623 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2313624 const HostPortPair host_port_pair("www.example.org", 8080);
lgarrona91df87f2014-12-05 00:51:3413625 scoped_ptr<SpdyFrame> connect(
13626 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
[email protected]cdf8f7e72013-05-23 10:56:4613627 scoped_ptr<SpdyFrame> req1(
rdsmithebb50aa2015-11-12 03:44:3813628 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
[email protected]23e482282013-06-14 16:08:0213629 scoped_ptr<SpdyFrame> wrapped_req1(
13630 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3913631
13632 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
[email protected]745aa9c2014-06-27 02:21:2913633 SpdyHeaderBlock req2_block;
bnc7ecc1122015-09-28 13:22:4913634 spdy_util_.MaybeAddVersionHeader(&req2_block);
[email protected]745aa9c2014-06-27 02:21:2913635 req2_block[spdy_util_.GetMethodKey()] = "GET";
bncce36dca22015-04-21 22:11:2313636 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
[email protected]745aa9c2014-06-27 02:21:2913637 req2_block[spdy_util_.GetSchemeKey()] = "http";
bnc7ecc1122015-09-28 13:22:4913638 req2_block[spdy_util_.GetPathKey()] = "/";
[email protected]601e03f12014-04-06 16:26:3913639 scoped_ptr<SpdyFrame> req2(
[email protected]745aa9c2014-06-27 02:21:2913640 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
[email protected]8450d722012-07-02 19:14:0413641
13642 MockWrite writes1[] = {
13643 CreateMockWrite(*connect, 0),
13644 CreateMockWrite(*wrapped_req1, 2),
13645 CreateMockWrite(*req2, 5),
13646 };
13647
[email protected]23e482282013-06-14 16:08:0213648 scoped_ptr<SpdyFrame> conn_resp(
13649 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13650 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13651 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
13652 scoped_ptr<SpdyFrame> wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3813653 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
[email protected]23e482282013-06-14 16:08:0213654 scoped_ptr<SpdyFrame> wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3813655 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
[email protected]23e482282013-06-14 16:08:0213656 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13657 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]8450d722012-07-02 19:14:0413658 MockRead reads1[] = {
13659 CreateMockRead(*conn_resp, 1),
13660 CreateMockRead(*wrapped_resp1, 3),
13661 CreateMockRead(*wrapped_body1, 4),
13662 CreateMockRead(*resp2, 6),
13663 CreateMockRead(*body2, 7),
13664 MockRead(ASYNC, ERR_IO_PENDING, 8)
13665 };
13666
[email protected]dd54bd82012-07-19 23:44:5713667 DeterministicSocketData data1(reads1, arraysize(reads1),
13668 writes1, arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0413669 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5713670 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0413671
rdsmith82957ad2015-09-16 19:42:0313672 session_deps_.proxy_service =
13673 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:5113674 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0713675 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0413676 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
rdsmithebb50aa2015-11-12 03:44:3813677 ssl1.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713678 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0413679 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
rdsmithebb50aa2015-11-12 03:44:3813680 ssl2.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713681 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
13682 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0413683
mmenkee65e7af2015-10-13 17:16:4213684 scoped_ptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:0713685 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
[email protected]8450d722012-07-02 19:14:0413686
13687 // Start the first transaction to set up the SpdySession
13688 HttpRequestInfo request1;
13689 request1.method = "GET";
13690 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0413691 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013692 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0413693 TestCompletionCallback callback1;
13694 EXPECT_EQ(ERR_IO_PENDING,
13695 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413696 base::MessageLoop::current()->RunUntilIdle();
[email protected]dd54bd82012-07-19 23:44:5713697 data1.RunFor(4);
[email protected]8450d722012-07-02 19:14:0413698
13699 EXPECT_EQ(OK, callback1.WaitForResult());
13700 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13701
[email protected]f6c63db52013-02-02 00:35:2213702 LoadTimingInfo load_timing_info1;
13703 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
13704 TestLoadTimingNotReusedWithPac(load_timing_info1,
13705 CONNECT_TIMING_HAS_SSL_TIMES);
13706
[email protected]8450d722012-07-02 19:14:0413707 // Now, start the HTTP request
13708 HttpRequestInfo request2;
13709 request2.method = "GET";
13710 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0413711 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013712 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0413713 TestCompletionCallback callback2;
13714 EXPECT_EQ(ERR_IO_PENDING,
13715 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413716 base::MessageLoop::current()->RunUntilIdle();
[email protected]dd54bd82012-07-19 23:44:5713717 data1.RunFor(3);
[email protected]8450d722012-07-02 19:14:0413718
13719 EXPECT_EQ(OK, callback2.WaitForResult());
13720 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2213721
13722 LoadTimingInfo load_timing_info2;
13723 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
13724 // The established SPDY sessions is considered reused by the HTTP request.
13725 TestLoadTimingReusedWithPac(load_timing_info2);
13726 // HTTP requests over a SPDY session should have a different connection
13727 // socket_log_id than requests over a tunnel.
13728 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0413729}
13730
[email protected]2d88e7d2012-07-19 17:55:1713731// Test that in the case where we have a SPDY session to a SPDY proxy
13732// that we do not pool other origins that resolve to the same IP when
13733// the certificate does not match the new origin.
13734// http://crbug.com/134690
[email protected]23e482282013-06-14 16:08:0213735TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2313736 const std::string url1 = "http://www.example.org/";
13737 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1713738 const std::string ip_addr = "1.2.3.4";
13739
rdsmithebb50aa2015-11-12 03:44:3813740 // Second SpdyTestUtil instance for the second socket.
13741 SpdyTestUtil spdy_util_secure(GetProtocol(), GetDependenciesFromPriority());
13742
[email protected]2d88e7d2012-07-19 17:55:1713743 // SPDY GET for HTTP URL (through SPDY proxy)
[email protected]23e482282013-06-14 16:08:0213744 scoped_ptr<SpdyHeaderBlock> headers(
bncce36dca22015-04-21 22:11:2313745 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
[email protected]745aa9c2014-06-27 02:21:2913746 scoped_ptr<SpdyFrame> req1(
13747 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]2d88e7d2012-07-19 17:55:1713748
13749 MockWrite writes1[] = {
13750 CreateMockWrite(*req1, 0),
13751 };
13752
[email protected]23e482282013-06-14 16:08:0213753 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13754 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1713755 MockRead reads1[] = {
bncb9e20fc62015-08-17 17:19:3713756 CreateMockRead(*resp1, 1),
13757 CreateMockRead(*body1, 2),
13758 MockRead(ASYNC, OK, 3) // EOF
[email protected]2d88e7d2012-07-19 17:55:1713759 };
13760
13761 scoped_ptr<DeterministicSocketData> data1(
13762 new DeterministicSocketData(reads1, arraysize(reads1),
13763 writes1, arraysize(writes1)));
13764 IPAddressNumber ip;
13765 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
13766 IPEndPoint peer_addr = IPEndPoint(ip, 443);
13767 MockConnect connect_data1(ASYNC, OK, peer_addr);
13768 data1->set_connect_data(connect_data1);
13769
13770 // SPDY GET for HTTPS URL (direct)
[email protected]cdf8f7e72013-05-23 10:56:4613771 scoped_ptr<SpdyFrame> req2(
rdsmithebb50aa2015-11-12 03:44:3813772 spdy_util_secure.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1713773
13774 MockWrite writes2[] = {
13775 CreateMockWrite(*req2, 0),
13776 };
13777
rdsmithebb50aa2015-11-12 03:44:3813778 scoped_ptr<SpdyFrame> resp2(
13779 spdy_util_secure.ConstructSpdyGetSynReply(NULL, 0, 1));
13780 scoped_ptr<SpdyFrame> body2(spdy_util_secure.ConstructSpdyBodyFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1713781 MockRead reads2[] = {
bncb9e20fc62015-08-17 17:19:3713782 CreateMockRead(*resp2, 1),
13783 CreateMockRead(*body2, 2),
13784 MockRead(ASYNC, OK, 3) // EOF
[email protected]2d88e7d2012-07-19 17:55:1713785 };
13786
13787 scoped_ptr<DeterministicSocketData> data2(
13788 new DeterministicSocketData(reads2, arraysize(reads2),
13789 writes2, arraysize(writes2)));
13790 MockConnect connect_data2(ASYNC, OK);
13791 data2->set_connect_data(connect_data2);
13792
13793 // Set up a proxy config that sends HTTP requests to a proxy, and
13794 // all others direct.
13795 ProxyConfig proxy_config;
13796 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
[email protected]bb88e1d32013-05-03 23:11:0713797 session_deps_.proxy_service.reset(new ProxyService(
csharrisonb7e3a082015-09-22 19:13:0413798 make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)), nullptr,
13799 NULL));
[email protected]2d88e7d2012-07-19 17:55:1713800
bncce36dca22015-04-21 22:11:2313801 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
rdsmithebb50aa2015-11-12 03:44:3813802 ssl1.SetNextProto(GetProtocol());
[email protected]2d88e7d2012-07-19 17:55:1713803 // Load a valid cert. Note, that this does not need to
13804 // be valid for proxy because the MockSSLClientSocket does
13805 // not actually verify it. But SpdySession will use this
13806 // to see if it is valid for the new origin
bncce36dca22015-04-21 22:11:2313807 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
13808 ASSERT_TRUE(ssl1.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0713809 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
13810 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
13811 data1.get());
[email protected]2d88e7d2012-07-19 17:55:1713812
13813 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
rdsmithebb50aa2015-11-12 03:44:3813814 ssl2.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713815 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
13816 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
13817 data2.get());
[email protected]2d88e7d2012-07-19 17:55:1713818
[email protected]bb88e1d32013-05-03 23:11:0713819 session_deps_.host_resolver.reset(new MockCachingHostResolver());
bncce36dca22015-04-21 22:11:2313820 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0713821 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1713822
mmenkee65e7af2015-10-13 17:16:4213823 scoped_ptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:0713824 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
[email protected]2d88e7d2012-07-19 17:55:1713825
13826 // Start the first transaction to set up the SpdySession
13827 HttpRequestInfo request1;
13828 request1.method = "GET";
13829 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1713830 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013831 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713832 TestCompletionCallback callback1;
13833 ASSERT_EQ(ERR_IO_PENDING,
13834 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
13835 data1->RunFor(3);
13836
13837 ASSERT_TRUE(callback1.have_result());
13838 EXPECT_EQ(OK, callback1.WaitForResult());
13839 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13840
13841 // Now, start the HTTP request
13842 HttpRequestInfo request2;
13843 request2.method = "GET";
13844 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1713845 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013846 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713847 TestCompletionCallback callback2;
13848 EXPECT_EQ(ERR_IO_PENDING,
13849 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413850 base::MessageLoop::current()->RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1713851 data2->RunFor(3);
13852
13853 ASSERT_TRUE(callback2.have_result());
13854 EXPECT_EQ(OK, callback2.WaitForResult());
13855 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13856}
13857
[email protected]85f97342013-04-17 06:12:2413858// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
13859// error) in SPDY session, removes the socket from pool and closes the SPDY
13860// session. Verify that new url's from the same HttpNetworkSession (and a new
13861// SpdySession) do work. http://crbug.com/224701
[email protected]23e482282013-06-14 16:08:0213862TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2313863 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2413864
13865 MockRead reads1[] = {
13866 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
13867 };
13868
mmenke11eb5152015-06-09 14:50:5013869 SequencedSocketData data1(reads1, arraysize(reads1), NULL, 0);
[email protected]85f97342013-04-17 06:12:2413870
[email protected]cdf8f7e72013-05-23 10:56:4613871 scoped_ptr<SpdyFrame> req2(
13872 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2413873 MockWrite writes2[] = {
13874 CreateMockWrite(*req2, 0),
13875 };
13876
[email protected]23e482282013-06-14 16:08:0213877 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13878 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]85f97342013-04-17 06:12:2413879 MockRead reads2[] = {
13880 CreateMockRead(*resp2, 1),
13881 CreateMockRead(*body2, 2),
13882 MockRead(ASYNC, OK, 3) // EOF
13883 };
13884
mmenke11eb5152015-06-09 14:50:5013885 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13886 arraysize(writes2));
[email protected]85f97342013-04-17 06:12:2413887
[email protected]85f97342013-04-17 06:12:2413888 SSLSocketDataProvider ssl1(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813889 ssl1.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:5013890 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13891 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2413892
13893 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813894 ssl2.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:5013895 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13896 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2413897
mmenkee65e7af2015-10-13 17:16:4213898 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5013899 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2413900
13901 // Start the first transaction to set up the SpdySession and verify that
13902 // connection was closed.
13903 HttpRequestInfo request1;
13904 request1.method = "GET";
13905 request1.url = GURL(https_url);
13906 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013907 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2413908 TestCompletionCallback callback1;
13909 EXPECT_EQ(ERR_IO_PENDING,
13910 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]85f97342013-04-17 06:12:2413911 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
13912
13913 // Now, start the second request and make sure it succeeds.
13914 HttpRequestInfo request2;
13915 request2.method = "GET";
13916 request2.url = GURL(https_url);
13917 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013918 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2413919 TestCompletionCallback callback2;
13920 EXPECT_EQ(ERR_IO_PENDING,
13921 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]85f97342013-04-17 06:12:2413922
mmenke11eb5152015-06-09 14:50:5013923 ASSERT_EQ(OK, callback2.WaitForResult());
[email protected]85f97342013-04-17 06:12:2413924 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13925}
13926
[email protected]23e482282013-06-14 16:08:0213927TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]d7599122014-05-24 03:37:2313928 session_deps_.next_protos = SpdyNextProtos();
[email protected]483fa202013-05-14 01:07:0313929 ClientSocketPoolManager::set_max_sockets_per_group(
13930 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13931 ClientSocketPoolManager::set_max_sockets_per_pool(
13932 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13933
13934 // Use two different hosts with different IPs so they don't get pooled.
13935 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
13936 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
mmenkee65e7af2015-10-13 17:16:4213937 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0313938
13939 SSLSocketDataProvider ssl1(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813940 ssl1.SetNextProto(GetProtocol());
[email protected]483fa202013-05-14 01:07:0313941 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813942 ssl2.SetNextProto(GetProtocol());
[email protected]483fa202013-05-14 01:07:0313943 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13944 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13945
[email protected]cdf8f7e72013-05-23 10:56:4613946 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
[email protected]483fa202013-05-14 01:07:0313947 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
13948 MockWrite spdy1_writes[] = {
rch8e6c6c42015-05-01 14:05:1313949 CreateMockWrite(*host1_req, 0),
[email protected]483fa202013-05-14 01:07:0313950 };
[email protected]23e482282013-06-14 16:08:0213951 scoped_ptr<SpdyFrame> host1_resp(
13952 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13953 scoped_ptr<SpdyFrame> host1_resp_body(
13954 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]483fa202013-05-14 01:07:0313955 MockRead spdy1_reads[] = {
rch8e6c6c42015-05-01 14:05:1313956 CreateMockRead(*host1_resp, 1),
13957 CreateMockRead(*host1_resp_body, 2),
13958 MockRead(ASYNC, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0313959 };
13960
rdsmithebb50aa2015-11-12 03:44:3813961 // Use a separate test instance for the separate SpdySession that will be
13962 // created.
13963 SpdyTestUtil spdy_util_2(GetProtocol(), GetDependenciesFromPriority());
rch8e6c6c42015-05-01 14:05:1313964 scoped_ptr<SequencedSocketData> spdy1_data(
13965 new SequencedSocketData(spdy1_reads, arraysize(spdy1_reads), spdy1_writes,
13966 arraysize(spdy1_writes)));
[email protected]483fa202013-05-14 01:07:0313967 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
13968
rdsmithebb50aa2015-11-12 03:44:3813969 scoped_ptr<SpdyFrame> host2_req(spdy_util_2.ConstructSpdyGet(
[email protected]483fa202013-05-14 01:07:0313970 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
13971 MockWrite spdy2_writes[] = {
rch8e6c6c42015-05-01 14:05:1313972 CreateMockWrite(*host2_req, 0),
[email protected]483fa202013-05-14 01:07:0313973 };
[email protected]23e482282013-06-14 16:08:0213974 scoped_ptr<SpdyFrame> host2_resp(
rdsmithebb50aa2015-11-12 03:44:3813975 spdy_util_2.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]23e482282013-06-14 16:08:0213976 scoped_ptr<SpdyFrame> host2_resp_body(
rdsmithebb50aa2015-11-12 03:44:3813977 spdy_util_2.ConstructSpdyBodyFrame(1, true));
[email protected]483fa202013-05-14 01:07:0313978 MockRead spdy2_reads[] = {
rch8e6c6c42015-05-01 14:05:1313979 CreateMockRead(*host2_resp, 1),
13980 CreateMockRead(*host2_resp_body, 2),
13981 MockRead(ASYNC, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0313982 };
13983
rch8e6c6c42015-05-01 14:05:1313984 scoped_ptr<SequencedSocketData> spdy2_data(
13985 new SequencedSocketData(spdy2_reads, arraysize(spdy2_reads), spdy2_writes,
13986 arraysize(spdy2_writes)));
[email protected]483fa202013-05-14 01:07:0313987 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
13988
13989 MockWrite http_write[] = {
13990 MockWrite("GET / HTTP/1.1\r\n"
13991 "Host: www.a.com\r\n"
13992 "Connection: keep-alive\r\n\r\n"),
13993 };
13994
13995 MockRead http_read[] = {
13996 MockRead("HTTP/1.1 200 OK\r\n"),
13997 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
13998 MockRead("Content-Length: 6\r\n\r\n"),
13999 MockRead("hello!"),
14000 };
14001 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
14002 http_write, arraysize(http_write));
14003 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14004
14005 HostPortPair host_port_pair_a("www.a.com", 443);
[email protected]e6d017652013-05-17 18:01:4014006 SpdySessionKey spdy_session_key_a(
[email protected]314b03992014-04-01 01:28:5314007 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0314008 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614009 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314010
14011 TestCompletionCallback callback;
14012 HttpRequestInfo request1;
14013 request1.method = "GET";
14014 request1.url = GURL("https://www.a.com/");
14015 request1.load_flags = 0;
14016 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5014017 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0314018
14019 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
14020 EXPECT_EQ(ERR_IO_PENDING, rv);
14021 EXPECT_EQ(OK, callback.WaitForResult());
14022
14023 const HttpResponseInfo* response = trans->GetResponseInfo();
14024 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5014025 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0214026 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0314027 EXPECT_TRUE(response->was_fetched_via_spdy);
14028 EXPECT_TRUE(response->was_npn_negotiated);
14029
14030 std::string response_data;
14031 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
14032 EXPECT_EQ("hello!", response_data);
14033 trans.reset();
14034 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2614035 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314036
14037 HostPortPair host_port_pair_b("www.b.com", 443);
[email protected]e6d017652013-05-17 18:01:4014038 SpdySessionKey spdy_session_key_b(
[email protected]314b03992014-04-01 01:28:5314039 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0314040 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614041 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0314042 HttpRequestInfo request2;
14043 request2.method = "GET";
14044 request2.url = GURL("https://www.b.com/");
14045 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5014046 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0314047
14048 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
14049 EXPECT_EQ(ERR_IO_PENDING, rv);
14050 EXPECT_EQ(OK, callback.WaitForResult());
14051
14052 response = trans->GetResponseInfo();
14053 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5014054 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0214055 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0314056 EXPECT_TRUE(response->was_fetched_via_spdy);
14057 EXPECT_TRUE(response->was_npn_negotiated);
14058 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
14059 EXPECT_EQ("hello!", response_data);
14060 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614061 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314062 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2614063 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0314064
14065 HostPortPair host_port_pair_a1("www.a.com", 80);
[email protected]e6d017652013-05-17 18:01:4014066 SpdySessionKey spdy_session_key_a1(
[email protected]314b03992014-04-01 01:28:5314067 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0314068 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614069 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0314070 HttpRequestInfo request3;
14071 request3.method = "GET";
14072 request3.url = GURL("http://www.a.com/");
14073 request3.load_flags = 0;
[email protected]90499482013-06-01 00:39:5014074 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0314075
14076 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
14077 EXPECT_EQ(ERR_IO_PENDING, rv);
14078 EXPECT_EQ(OK, callback.WaitForResult());
14079
14080 response = trans->GetResponseInfo();
14081 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5014082 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]483fa202013-05-14 01:07:0314083 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14084 EXPECT_FALSE(response->was_fetched_via_spdy);
14085 EXPECT_FALSE(response->was_npn_negotiated);
14086 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
14087 EXPECT_EQ("hello!", response_data);
14088 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614089 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314090 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614091 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0314092}
14093
[email protected]79e1fd62013-06-20 06:50:0414094TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
14095 HttpRequestInfo request;
14096 request.method = "GET";
bncce36dca22015-04-21 22:11:2314097 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414098 request.load_flags = 0;
14099
mmenkee65e7af2015-10-13 17:16:4214100 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414101 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114102 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414103
ttuttled9dbc652015-09-29 20:00:5914104 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0414105 StaticSocketDataProvider data;
14106 data.set_connect_data(mock_connect);
14107 session_deps_.socket_factory->AddSocketDataProvider(&data);
14108
14109 TestCompletionCallback callback;
14110
14111 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14112 EXPECT_EQ(ERR_IO_PENDING, rv);
14113
14114 rv = callback.WaitForResult();
ttuttled9dbc652015-09-29 20:00:5914115 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
[email protected]79e1fd62013-06-20 06:50:0414116
[email protected]79e1fd62013-06-20 06:50:0414117 // We don't care whether this succeeds or fails, but it shouldn't crash.
14118 HttpRequestHeaders request_headers;
14119 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4714120
14121 ConnectionAttempts attempts;
14122 trans->GetConnectionAttempts(&attempts);
14123 ASSERT_EQ(1u, attempts.size());
ttuttled9dbc652015-09-29 20:00:5914124 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
14125
14126 IPEndPoint endpoint;
14127 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
14128 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0414129}
14130
14131TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
14132 HttpRequestInfo request;
14133 request.method = "GET";
bncce36dca22015-04-21 22:11:2314134 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414135 request.load_flags = 0;
14136
mmenkee65e7af2015-10-13 17:16:4214137 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414138 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114139 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414140
ttuttled9dbc652015-09-29 20:00:5914141 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0414142 StaticSocketDataProvider data;
14143 data.set_connect_data(mock_connect);
14144 session_deps_.socket_factory->AddSocketDataProvider(&data);
14145
14146 TestCompletionCallback callback;
14147
14148 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14149 EXPECT_EQ(ERR_IO_PENDING, rv);
14150
14151 rv = callback.WaitForResult();
ttuttled9dbc652015-09-29 20:00:5914152 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
[email protected]79e1fd62013-06-20 06:50:0414153
[email protected]79e1fd62013-06-20 06:50:0414154 // We don't care whether this succeeds or fails, but it shouldn't crash.
14155 HttpRequestHeaders request_headers;
14156 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4714157
14158 ConnectionAttempts attempts;
14159 trans->GetConnectionAttempts(&attempts);
14160 ASSERT_EQ(1u, attempts.size());
ttuttled9dbc652015-09-29 20:00:5914161 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
14162
14163 IPEndPoint endpoint;
14164 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
14165 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0414166}
14167
14168TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
14169 HttpRequestInfo request;
14170 request.method = "GET";
bncce36dca22015-04-21 22:11:2314171 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414172 request.load_flags = 0;
14173
mmenkee65e7af2015-10-13 17:16:4214174 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414175 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114176 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414177
14178 MockWrite data_writes[] = {
14179 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14180 };
14181 MockRead data_reads[] = {
14182 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
14183 };
14184
14185 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14186 data_writes, arraysize(data_writes));
14187 session_deps_.socket_factory->AddSocketDataProvider(&data);
14188
14189 TestCompletionCallback callback;
14190
14191 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14192 EXPECT_EQ(ERR_IO_PENDING, rv);
14193
14194 rv = callback.WaitForResult();
14195 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14196
[email protected]79e1fd62013-06-20 06:50:0414197 HttpRequestHeaders request_headers;
14198 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14199 EXPECT_TRUE(request_headers.HasHeader("Host"));
14200}
14201
14202TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
14203 HttpRequestInfo request;
14204 request.method = "GET";
bncce36dca22015-04-21 22:11:2314205 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414206 request.load_flags = 0;
14207
mmenkee65e7af2015-10-13 17:16:4214208 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414209 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114210 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414211
14212 MockWrite data_writes[] = {
14213 MockWrite(ASYNC, ERR_CONNECTION_RESET),
14214 };
14215 MockRead data_reads[] = {
14216 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
14217 };
14218
14219 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14220 data_writes, arraysize(data_writes));
14221 session_deps_.socket_factory->AddSocketDataProvider(&data);
14222
14223 TestCompletionCallback callback;
14224
14225 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14226 EXPECT_EQ(ERR_IO_PENDING, rv);
14227
14228 rv = callback.WaitForResult();
14229 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14230
[email protected]79e1fd62013-06-20 06:50:0414231 HttpRequestHeaders request_headers;
14232 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14233 EXPECT_TRUE(request_headers.HasHeader("Host"));
14234}
14235
14236TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
14237 HttpRequestInfo request;
14238 request.method = "GET";
bncce36dca22015-04-21 22:11:2314239 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414240 request.load_flags = 0;
14241
mmenkee65e7af2015-10-13 17:16:4214242 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414243 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114244 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414245
14246 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314247 MockWrite(
14248 "GET / HTTP/1.1\r\n"
14249 "Host: www.example.org\r\n"
14250 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414251 };
14252 MockRead data_reads[] = {
14253 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
14254 };
14255
14256 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14257 data_writes, arraysize(data_writes));
14258 session_deps_.socket_factory->AddSocketDataProvider(&data);
14259
14260 TestCompletionCallback callback;
14261
14262 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14263 EXPECT_EQ(ERR_IO_PENDING, rv);
14264
14265 rv = callback.WaitForResult();
14266 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14267
[email protected]79e1fd62013-06-20 06:50:0414268 HttpRequestHeaders request_headers;
14269 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14270 EXPECT_TRUE(request_headers.HasHeader("Host"));
14271}
14272
14273TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
14274 HttpRequestInfo request;
14275 request.method = "GET";
bncce36dca22015-04-21 22:11:2314276 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414277 request.load_flags = 0;
14278
mmenkee65e7af2015-10-13 17:16:4214279 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414280 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114281 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414282
14283 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314284 MockWrite(
14285 "GET / HTTP/1.1\r\n"
14286 "Host: www.example.org\r\n"
14287 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414288 };
14289 MockRead data_reads[] = {
14290 MockRead(ASYNC, ERR_CONNECTION_RESET),
14291 };
14292
14293 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14294 data_writes, arraysize(data_writes));
14295 session_deps_.socket_factory->AddSocketDataProvider(&data);
14296
14297 TestCompletionCallback callback;
14298
14299 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14300 EXPECT_EQ(ERR_IO_PENDING, rv);
14301
14302 rv = callback.WaitForResult();
14303 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14304
[email protected]79e1fd62013-06-20 06:50:0414305 HttpRequestHeaders request_headers;
14306 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14307 EXPECT_TRUE(request_headers.HasHeader("Host"));
14308}
14309
14310TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
14311 HttpRequestInfo request;
14312 request.method = "GET";
bncce36dca22015-04-21 22:11:2314313 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414314 request.load_flags = 0;
14315 request.extra_headers.SetHeader("X-Foo", "bar");
14316
mmenkee65e7af2015-10-13 17:16:4214317 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414318 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114319 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414320
14321 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314322 MockWrite(
14323 "GET / HTTP/1.1\r\n"
14324 "Host: www.example.org\r\n"
14325 "Connection: keep-alive\r\n"
14326 "X-Foo: bar\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414327 };
14328 MockRead data_reads[] = {
14329 MockRead("HTTP/1.1 200 OK\r\n"
14330 "Content-Length: 5\r\n\r\n"
14331 "hello"),
14332 MockRead(ASYNC, ERR_UNEXPECTED),
14333 };
14334
14335 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14336 data_writes, arraysize(data_writes));
14337 session_deps_.socket_factory->AddSocketDataProvider(&data);
14338
14339 TestCompletionCallback callback;
14340
14341 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14342 EXPECT_EQ(ERR_IO_PENDING, rv);
14343
14344 rv = callback.WaitForResult();
14345 EXPECT_EQ(OK, rv);
14346
14347 HttpRequestHeaders request_headers;
14348 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14349 std::string foo;
14350 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
14351 EXPECT_EQ("bar", foo);
14352}
14353
[email protected]bf828982013-08-14 18:01:4714354namespace {
14355
yhiranoa7e05bb2014-11-06 05:40:3914356// Fake HttpStream that simply records calls to SetPriority().
14357class FakeStream : public HttpStream,
[email protected]e86839fd2013-08-14 18:29:0314358 public base::SupportsWeakPtr<FakeStream> {
14359 public:
14360 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
dchengb03027d2014-10-21 12:00:2014361 ~FakeStream() override {}
[email protected]e86839fd2013-08-14 18:29:0314362
14363 RequestPriority priority() const { return priority_; }
14364
dchengb03027d2014-10-21 12:00:2014365 int InitializeStream(const HttpRequestInfo* request_info,
14366 RequestPriority priority,
14367 const BoundNetLog& net_log,
14368 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314369 return ERR_IO_PENDING;
14370 }
14371
dchengb03027d2014-10-21 12:00:2014372 int SendRequest(const HttpRequestHeaders& request_headers,
14373 HttpResponseInfo* response,
14374 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314375 ADD_FAILURE();
14376 return ERR_UNEXPECTED;
14377 }
14378
dchengb03027d2014-10-21 12:00:2014379 int ReadResponseHeaders(const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314380 ADD_FAILURE();
14381 return ERR_UNEXPECTED;
14382 }
14383
dchengb03027d2014-10-21 12:00:2014384 int ReadResponseBody(IOBuffer* buf,
14385 int buf_len,
14386 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314387 ADD_FAILURE();
14388 return ERR_UNEXPECTED;
14389 }
14390
dchengb03027d2014-10-21 12:00:2014391 void Close(bool not_reusable) override {}
[email protected]e86839fd2013-08-14 18:29:0314392
dchengb03027d2014-10-21 12:00:2014393 bool IsResponseBodyComplete() const override {
[email protected]e86839fd2013-08-14 18:29:0314394 ADD_FAILURE();
14395 return false;
14396 }
14397
dchengb03027d2014-10-21 12:00:2014398 bool IsConnectionReused() const override {
[email protected]e86839fd2013-08-14 18:29:0314399 ADD_FAILURE();
14400 return false;
14401 }
14402
dchengb03027d2014-10-21 12:00:2014403 void SetConnectionReused() override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0314404
mmenkebd84c392015-09-02 14:12:3414405 bool CanReuseConnection() const override { return false; }
[email protected]e86839fd2013-08-14 18:29:0314406
sclittle4de1bab92015-09-22 21:28:2414407 int64_t GetTotalReceivedBytes() const override {
[email protected]bc92bc972013-12-13 08:32:5914408 ADD_FAILURE();
14409 return 0;
14410 }
14411
sclittlebe1ccf62015-09-02 19:40:3614412 int64_t GetTotalSentBytes() const override {
14413 ADD_FAILURE();
14414 return 0;
14415 }
14416
dchengb03027d2014-10-21 12:00:2014417 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
[email protected]e86839fd2013-08-14 18:29:0314418 ADD_FAILURE();
14419 return false;
14420 }
14421
dchengb03027d2014-10-21 12:00:2014422 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
14423
14424 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
[email protected]e86839fd2013-08-14 18:29:0314425 ADD_FAILURE();
14426 }
14427
ttuttled9dbc652015-09-29 20:00:5914428 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
14429
dchengb03027d2014-10-21 12:00:2014430 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0314431
dchengb03027d2014-10-21 12:00:2014432 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]e86839fd2013-08-14 18:29:0314433
yhiranoa7e05bb2014-11-06 05:40:3914434 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
14435
14436 HttpStream* RenewStreamForAuth() override { return NULL; }
14437
[email protected]e86839fd2013-08-14 18:29:0314438 private:
14439 RequestPriority priority_;
14440
14441 DISALLOW_COPY_AND_ASSIGN(FakeStream);
14442};
14443
14444// Fake HttpStreamRequest that simply records calls to SetPriority()
14445// and vends FakeStreams with its current priority.
[email protected]bf828982013-08-14 18:01:4714446class FakeStreamRequest : public HttpStreamRequest,
14447 public base::SupportsWeakPtr<FakeStreamRequest> {
14448 public:
[email protected]e86839fd2013-08-14 18:29:0314449 FakeStreamRequest(RequestPriority priority,
14450 HttpStreamRequest::Delegate* delegate)
14451 : priority_(priority),
[email protected]831e4a32013-11-14 02:14:4414452 delegate_(delegate),
14453 websocket_stream_create_helper_(NULL) {}
14454
14455 FakeStreamRequest(RequestPriority priority,
14456 HttpStreamRequest::Delegate* delegate,
14457 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
14458 : priority_(priority),
14459 delegate_(delegate),
14460 websocket_stream_create_helper_(create_helper) {}
[email protected]e86839fd2013-08-14 18:29:0314461
dchengb03027d2014-10-21 12:00:2014462 ~FakeStreamRequest() override {}
[email protected]bf828982013-08-14 18:01:4714463
14464 RequestPriority priority() const { return priority_; }
14465
[email protected]831e4a32013-11-14 02:14:4414466 const WebSocketHandshakeStreamBase::CreateHelper*
14467 websocket_stream_create_helper() const {
14468 return websocket_stream_create_helper_;
14469 }
14470
[email protected]e86839fd2013-08-14 18:29:0314471 // Create a new FakeStream and pass it to the request's
14472 // delegate. Returns a weak pointer to the FakeStream.
14473 base::WeakPtr<FakeStream> FinishStreamRequest() {
14474 FakeStream* fake_stream = new FakeStream(priority_);
14475 // Do this before calling OnStreamReady() as OnStreamReady() may
14476 // immediately delete |fake_stream|.
14477 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
14478 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
14479 return weak_stream;
14480 }
14481
dchengb03027d2014-10-21 12:00:2014482 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
[email protected]bf828982013-08-14 18:01:4714483 ADD_FAILURE();
14484 return ERR_UNEXPECTED;
14485 }
14486
dchengb03027d2014-10-21 12:00:2014487 LoadState GetLoadState() const override {
[email protected]bf828982013-08-14 18:01:4714488 ADD_FAILURE();
14489 return LoadState();
14490 }
14491
dchengb03027d2014-10-21 12:00:2014492 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]bf828982013-08-14 18:01:4714493
dchengb03027d2014-10-21 12:00:2014494 bool was_npn_negotiated() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714495
dchengb03027d2014-10-21 12:00:2014496 NextProto protocol_negotiated() const override { return kProtoUnknown; }
[email protected]bf828982013-08-14 18:01:4714497
dchengb03027d2014-10-21 12:00:2014498 bool using_spdy() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714499
ttuttle1f2d7e92015-04-28 16:17:4714500 const ConnectionAttempts& connection_attempts() const override {
14501 static ConnectionAttempts no_attempts;
14502 return no_attempts;
14503 }
14504
[email protected]bf828982013-08-14 18:01:4714505 private:
14506 RequestPriority priority_;
[email protected]e86839fd2013-08-14 18:29:0314507 HttpStreamRequest::Delegate* const delegate_;
[email protected]831e4a32013-11-14 02:14:4414508 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
[email protected]bf828982013-08-14 18:01:4714509
14510 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
14511};
14512
14513// Fake HttpStreamFactory that vends FakeStreamRequests.
14514class FakeStreamFactory : public HttpStreamFactory {
14515 public:
14516 FakeStreamFactory() {}
dchengb03027d2014-10-21 12:00:2014517 ~FakeStreamFactory() override {}
[email protected]bf828982013-08-14 18:01:4714518
14519 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
14520 // RequestStream() (which may be NULL if it was destroyed already).
14521 base::WeakPtr<FakeStreamRequest> last_stream_request() {
14522 return last_stream_request_;
14523 }
14524
dchengb03027d2014-10-21 12:00:2014525 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
14526 RequestPriority priority,
14527 const SSLConfig& server_ssl_config,
14528 const SSLConfig& proxy_ssl_config,
14529 HttpStreamRequest::Delegate* delegate,
14530 const BoundNetLog& net_log) override {
[email protected]e86839fd2013-08-14 18:29:0314531 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
[email protected]bf828982013-08-14 18:01:4714532 last_stream_request_ = fake_request->AsWeakPtr();
14533 return fake_request;
14534 }
14535
dchengb03027d2014-10-21 12:00:2014536 HttpStreamRequest* RequestWebSocketHandshakeStream(
[email protected]bf828982013-08-14 18:01:4714537 const HttpRequestInfo& info,
14538 RequestPriority priority,
14539 const SSLConfig& server_ssl_config,
14540 const SSLConfig& proxy_ssl_config,
14541 HttpStreamRequest::Delegate* delegate,
[email protected]467086b2013-11-12 08:19:4614542 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
mostynbba063d6032014-10-09 11:01:1314543 const BoundNetLog& net_log) override {
[email protected]831e4a32013-11-14 02:14:4414544 FakeStreamRequest* fake_request =
14545 new FakeStreamRequest(priority, delegate, create_helper);
14546 last_stream_request_ = fake_request->AsWeakPtr();
14547 return fake_request;
[email protected]bf828982013-08-14 18:01:4714548 }
14549
dchengb03027d2014-10-21 12:00:2014550 void PreconnectStreams(int num_streams,
14551 const HttpRequestInfo& info,
dchengb03027d2014-10-21 12:00:2014552 const SSLConfig& server_ssl_config,
14553 const SSLConfig& proxy_ssl_config) override {
[email protected]bf828982013-08-14 18:01:4714554 ADD_FAILURE();
14555 }
14556
dchengb03027d2014-10-21 12:00:2014557 const HostMappingRules* GetHostMappingRules() const override {
[email protected]bf828982013-08-14 18:01:4714558 ADD_FAILURE();
14559 return NULL;
14560 }
14561
14562 private:
14563 base::WeakPtr<FakeStreamRequest> last_stream_request_;
14564
14565 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
14566};
14567
Adam Rice425cf122015-01-19 06:18:2414568// TODO(ricea): Maybe unify this with the one in
14569// url_request_http_job_unittest.cc ?
14570class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
14571 public:
14572 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection,
14573 bool using_proxy)
14574 : state_(connection.release(), using_proxy) {}
14575
14576 // Fake implementation of HttpStreamBase methods.
14577 // This ends up being quite "real" because this object has to really send data
14578 // on the mock socket. It might be easier to use the real implementation, but
14579 // the fact that the WebSocket code is not compiled on iOS makes that
14580 // difficult.
14581 int InitializeStream(const HttpRequestInfo* request_info,
14582 RequestPriority priority,
14583 const BoundNetLog& net_log,
14584 const CompletionCallback& callback) override {
14585 state_.Initialize(request_info, priority, net_log, callback);
14586 return OK;
14587 }
14588
14589 int SendRequest(const HttpRequestHeaders& request_headers,
14590 HttpResponseInfo* response,
14591 const CompletionCallback& callback) override {
14592 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
14593 response, callback);
14594 }
14595
14596 int ReadResponseHeaders(const CompletionCallback& callback) override {
14597 return parser()->ReadResponseHeaders(callback);
14598 }
14599
14600 int ReadResponseBody(IOBuffer* buf,
14601 int buf_len,
14602 const CompletionCallback& callback) override {
14603 NOTREACHED();
14604 return ERR_IO_PENDING;
14605 }
14606
14607 void Close(bool not_reusable) override {
14608 if (parser())
14609 parser()->Close(true);
14610 }
14611
14612 bool IsResponseBodyComplete() const override {
14613 NOTREACHED();
14614 return false;
14615 }
14616
Adam Rice425cf122015-01-19 06:18:2414617 bool IsConnectionReused() const override {
14618 NOTREACHED();
14619 return false;
14620 }
14621 void SetConnectionReused() override { NOTREACHED(); }
14622
mmenkebd84c392015-09-02 14:12:3414623 bool CanReuseConnection() const override { return false; }
Adam Rice425cf122015-01-19 06:18:2414624
sclittle4de1bab92015-09-22 21:28:2414625 int64_t GetTotalReceivedBytes() const override {
Adam Rice425cf122015-01-19 06:18:2414626 NOTREACHED();
14627 return 0;
14628 }
14629
sclittlebe1ccf62015-09-02 19:40:3614630 int64_t GetTotalSentBytes() const override {
14631 NOTREACHED();
14632 return 0;
14633 }
14634
Adam Rice425cf122015-01-19 06:18:2414635 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
14636 NOTREACHED();
14637 return false;
14638 }
14639
Adam Ricecb76ac62015-02-20 05:33:2514640 void GetSSLInfo(SSLInfo* ssl_info) override {}
Adam Rice425cf122015-01-19 06:18:2414641
14642 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
14643 NOTREACHED();
14644 }
14645
ttuttled9dbc652015-09-29 20:00:5914646 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
14647
Adam Rice425cf122015-01-19 06:18:2414648 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
14649
14650 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
14651
14652 UploadProgress GetUploadProgress() const override {
14653 NOTREACHED();
14654 return UploadProgress();
14655 }
14656
14657 HttpStream* RenewStreamForAuth() override {
14658 NOTREACHED();
14659 return nullptr;
14660 }
14661
14662 // Fake implementation of WebSocketHandshakeStreamBase method(s)
14663 scoped_ptr<WebSocketStream> Upgrade() override {
14664 NOTREACHED();
14665 return scoped_ptr<WebSocketStream>();
14666 }
14667
14668 private:
14669 HttpStreamParser* parser() const { return state_.parser(); }
14670 HttpBasicState state_;
14671
14672 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
14673};
14674
[email protected]831e4a32013-11-14 02:14:4414675// TODO(yhirano): Split this class out into a net/websockets file, if it is
14676// worth doing.
14677class FakeWebSocketStreamCreateHelper :
14678 public WebSocketHandshakeStreamBase::CreateHelper {
14679 public:
dchengb03027d2014-10-21 12:00:2014680 WebSocketHandshakeStreamBase* CreateBasicStream(
[email protected]7e841a52013-11-22 09:04:2114681 scoped_ptr<ClientSocketHandle> connection,
mostynbba063d6032014-10-09 11:01:1314682 bool using_proxy) override {
Adam Rice425cf122015-01-19 06:18:2414683 return new FakeWebSocketBasicHandshakeStream(connection.Pass(),
14684 using_proxy);
[email protected]831e4a32013-11-14 02:14:4414685 }
14686
dchengb03027d2014-10-21 12:00:2014687 WebSocketHandshakeStreamBase* CreateSpdyStream(
[email protected]831e4a32013-11-14 02:14:4414688 const base::WeakPtr<SpdySession>& session,
mostynbba063d6032014-10-09 11:01:1314689 bool use_relative_url) override {
[email protected]831e4a32013-11-14 02:14:4414690 NOTREACHED();
14691 return NULL;
14692 };
14693
dchengb03027d2014-10-21 12:00:2014694 ~FakeWebSocketStreamCreateHelper() override {}
[email protected]831e4a32013-11-14 02:14:4414695
14696 virtual scoped_ptr<WebSocketStream> Upgrade() {
14697 NOTREACHED();
14698 return scoped_ptr<WebSocketStream>();
14699 }
14700};
14701
[email protected]bf828982013-08-14 18:01:4714702} // namespace
14703
14704// Make sure that HttpNetworkTransaction passes on its priority to its
14705// stream request on start.
14706TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
mmenkee65e7af2015-10-13 17:16:4214707 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14708 HttpNetworkSessionPeer peer(session.get());
[email protected]bf828982013-08-14 18:01:4714709 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414710 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714711
dcheng48459ac22014-08-26 00:46:4114712 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714713
14714 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
14715
14716 HttpRequestInfo request;
14717 TestCompletionCallback callback;
14718 EXPECT_EQ(ERR_IO_PENDING,
14719 trans.Start(&request, callback.callback(), BoundNetLog()));
14720
14721 base::WeakPtr<FakeStreamRequest> fake_request =
14722 fake_factory->last_stream_request();
14723 ASSERT_TRUE(fake_request != NULL);
14724 EXPECT_EQ(LOW, fake_request->priority());
14725}
14726
14727// Make sure that HttpNetworkTransaction passes on its priority
14728// updates to its stream request.
14729TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
mmenkee65e7af2015-10-13 17:16:4214730 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14731 HttpNetworkSessionPeer peer(session.get());
[email protected]bf828982013-08-14 18:01:4714732 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414733 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714734
dcheng48459ac22014-08-26 00:46:4114735 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714736
14737 HttpRequestInfo request;
14738 TestCompletionCallback callback;
14739 EXPECT_EQ(ERR_IO_PENDING,
14740 trans.Start(&request, callback.callback(), BoundNetLog()));
14741
14742 base::WeakPtr<FakeStreamRequest> fake_request =
14743 fake_factory->last_stream_request();
14744 ASSERT_TRUE(fake_request != NULL);
14745 EXPECT_EQ(LOW, fake_request->priority());
14746
14747 trans.SetPriority(LOWEST);
14748 ASSERT_TRUE(fake_request != NULL);
14749 EXPECT_EQ(LOWEST, fake_request->priority());
14750}
14751
[email protected]e86839fd2013-08-14 18:29:0314752// Make sure that HttpNetworkTransaction passes on its priority
14753// updates to its stream.
14754TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
mmenkee65e7af2015-10-13 17:16:4214755 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14756 HttpNetworkSessionPeer peer(session.get());
[email protected]e86839fd2013-08-14 18:29:0314757 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414758 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]e86839fd2013-08-14 18:29:0314759
dcheng48459ac22014-08-26 00:46:4114760 HttpNetworkTransaction trans(LOW, session.get());
[email protected]e86839fd2013-08-14 18:29:0314761
14762 HttpRequestInfo request;
14763 TestCompletionCallback callback;
14764 EXPECT_EQ(ERR_IO_PENDING,
14765 trans.Start(&request, callback.callback(), BoundNetLog()));
14766
14767 base::WeakPtr<FakeStreamRequest> fake_request =
14768 fake_factory->last_stream_request();
14769 ASSERT_TRUE(fake_request != NULL);
14770 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
14771 ASSERT_TRUE(fake_stream != NULL);
14772 EXPECT_EQ(LOW, fake_stream->priority());
14773
14774 trans.SetPriority(LOWEST);
14775 EXPECT_EQ(LOWEST, fake_stream->priority());
14776}
14777
[email protected]831e4a32013-11-14 02:14:4414778TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
14779 // The same logic needs to be tested for both ws: and wss: schemes, but this
14780 // test is already parameterised on NextProto, so it uses a loop to verify
14781 // that the different schemes work.
bncce36dca22015-04-21 22:11:2314782 std::string test_cases[] = {"ws://www.example.org/",
14783 "wss://www.example.org/"};
[email protected]831e4a32013-11-14 02:14:4414784 for (size_t i = 0; i < arraysize(test_cases); ++i) {
mmenkee65e7af2015-10-13 17:16:4214785 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14786 HttpNetworkSessionPeer peer(session.get());
[email protected]831e4a32013-11-14 02:14:4414787 FakeStreamFactory* fake_factory = new FakeStreamFactory();
14788 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
[email protected]0191b51c2013-11-18 10:55:2314789 peer.SetHttpStreamFactoryForWebSocket(
[email protected]831e4a32013-11-14 02:14:4414790 scoped_ptr<HttpStreamFactory>(fake_factory));
14791
dcheng48459ac22014-08-26 00:46:4114792 HttpNetworkTransaction trans(LOW, session.get());
[email protected]831e4a32013-11-14 02:14:4414793 trans.SetWebSocketHandshakeStreamCreateHelper(
14794 &websocket_stream_create_helper);
14795
14796 HttpRequestInfo request;
14797 TestCompletionCallback callback;
14798 request.method = "GET";
14799 request.url = GURL(test_cases[i]);
14800
14801 EXPECT_EQ(ERR_IO_PENDING,
14802 trans.Start(&request, callback.callback(), BoundNetLog()));
14803
14804 base::WeakPtr<FakeStreamRequest> fake_request =
14805 fake_factory->last_stream_request();
14806 ASSERT_TRUE(fake_request != NULL);
14807 EXPECT_EQ(&websocket_stream_create_helper,
14808 fake_request->websocket_stream_create_helper());
14809 }
14810}
14811
[email protected]043b68c82013-08-22 23:41:5214812// Tests that when a used socket is returned to the SSL socket pool, it's closed
14813// if the transport socket pool is stalled on the global socket limit.
14814TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
14815 ClientSocketPoolManager::set_max_sockets_per_group(
14816 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14817 ClientSocketPoolManager::set_max_sockets_per_pool(
14818 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14819
14820 // Set up SSL request.
14821
14822 HttpRequestInfo ssl_request;
14823 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2314824 ssl_request.url = GURL("https://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214825
14826 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2314827 MockWrite(
14828 "GET / HTTP/1.1\r\n"
14829 "Host: www.example.org\r\n"
14830 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214831 };
14832 MockRead ssl_reads[] = {
14833 MockRead("HTTP/1.1 200 OK\r\n"),
14834 MockRead("Content-Length: 11\r\n\r\n"),
14835 MockRead("hello world"),
14836 MockRead(SYNCHRONOUS, OK),
14837 };
14838 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
14839 ssl_writes, arraysize(ssl_writes));
14840 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
14841
14842 SSLSocketDataProvider ssl(ASYNC, OK);
14843 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14844
14845 // Set up HTTP request.
14846
14847 HttpRequestInfo http_request;
14848 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2314849 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214850
14851 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2314852 MockWrite(
14853 "GET / HTTP/1.1\r\n"
14854 "Host: www.example.org\r\n"
14855 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214856 };
14857 MockRead http_reads[] = {
14858 MockRead("HTTP/1.1 200 OK\r\n"),
14859 MockRead("Content-Length: 7\r\n\r\n"),
14860 MockRead("falafel"),
14861 MockRead(SYNCHRONOUS, OK),
14862 };
14863 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
14864 http_writes, arraysize(http_writes));
14865 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14866
mmenkee65e7af2015-10-13 17:16:4214867 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5214868
14869 // Start the SSL request.
14870 TestCompletionCallback ssl_callback;
14871 scoped_ptr<HttpTransaction> ssl_trans(
14872 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14873 ASSERT_EQ(ERR_IO_PENDING,
14874 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
14875 BoundNetLog()));
14876
14877 // Start the HTTP request. Pool should stall.
14878 TestCompletionCallback http_callback;
14879 scoped_ptr<HttpTransaction> http_trans(
14880 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14881 ASSERT_EQ(ERR_IO_PENDING,
14882 http_trans->Start(&http_request, http_callback.callback(),
14883 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4114884 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214885
14886 // Wait for response from SSL request.
14887 ASSERT_EQ(OK, ssl_callback.WaitForResult());
14888 std::string response_data;
14889 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
14890 EXPECT_EQ("hello world", response_data);
14891
14892 // The SSL socket should automatically be closed, so the HTTP request can
14893 // start.
dcheng48459ac22014-08-26 00:46:4114894 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
14895 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214896
14897 // The HTTP request can now complete.
14898 ASSERT_EQ(OK, http_callback.WaitForResult());
14899 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
14900 EXPECT_EQ("falafel", response_data);
14901
dcheng48459ac22014-08-26 00:46:4114902 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214903}
14904
14905// Tests that when a SSL connection is established but there's no corresponding
14906// request that needs it, the new socket is closed if the transport socket pool
14907// is stalled on the global socket limit.
14908TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
14909 ClientSocketPoolManager::set_max_sockets_per_group(
14910 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14911 ClientSocketPoolManager::set_max_sockets_per_pool(
14912 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14913
14914 // Set up an ssl request.
14915
14916 HttpRequestInfo ssl_request;
14917 ssl_request.method = "GET";
14918 ssl_request.url = GURL("https://www.foopy.com/");
14919
14920 // No data will be sent on the SSL socket.
14921 StaticSocketDataProvider ssl_data;
14922 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
14923
14924 SSLSocketDataProvider ssl(ASYNC, OK);
14925 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14926
14927 // Set up HTTP request.
14928
14929 HttpRequestInfo http_request;
14930 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2314931 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214932
14933 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2314934 MockWrite(
14935 "GET / HTTP/1.1\r\n"
14936 "Host: www.example.org\r\n"
14937 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214938 };
14939 MockRead http_reads[] = {
14940 MockRead("HTTP/1.1 200 OK\r\n"),
14941 MockRead("Content-Length: 7\r\n\r\n"),
14942 MockRead("falafel"),
14943 MockRead(SYNCHRONOUS, OK),
14944 };
14945 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
14946 http_writes, arraysize(http_writes));
14947 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14948
mmenkee65e7af2015-10-13 17:16:4214949 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5214950
14951 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
14952 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2914953 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
14954 SSLConfig ssl_config;
[email protected]043b68c82013-08-22 23:41:5214955 session->ssl_config_service()->GetSSLConfig(&ssl_config);
mmenked1205bd2015-07-15 22:26:3514956 http_stream_factory->PreconnectStreams(1, ssl_request, ssl_config,
14957 ssl_config);
dcheng48459ac22014-08-26 00:46:4114958 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214959
14960 // Start the HTTP request. Pool should stall.
14961 TestCompletionCallback http_callback;
14962 scoped_ptr<HttpTransaction> http_trans(
14963 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14964 ASSERT_EQ(ERR_IO_PENDING,
14965 http_trans->Start(&http_request, http_callback.callback(),
14966 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4114967 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214968
14969 // The SSL connection will automatically be closed once the connection is
14970 // established, to let the HTTP request start.
14971 ASSERT_EQ(OK, http_callback.WaitForResult());
14972 std::string response_data;
14973 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
14974 EXPECT_EQ("falafel", response_data);
14975
dcheng48459ac22014-08-26 00:46:4114976 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214977}
14978
[email protected]02d74a02014-04-23 18:10:5414979TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2214980 std::vector<scoped_ptr<UploadElementReader>> element_readers;
14981 element_readers.push_back(
14982 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
14983 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5414984
14985 HttpRequestInfo request;
14986 request.method = "POST";
14987 request.url = GURL("http://www.foo.com/");
14988 request.upload_data_stream = &upload_data_stream;
14989 request.load_flags = 0;
14990
mmenkee65e7af2015-10-13 17:16:4214991 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414992 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114993 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414994 // Send headers successfully, but get an error while sending the body.
14995 MockWrite data_writes[] = {
14996 MockWrite("POST / HTTP/1.1\r\n"
14997 "Host: www.foo.com\r\n"
14998 "Connection: keep-alive\r\n"
14999 "Content-Length: 3\r\n\r\n"),
15000 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15001 };
15002
15003 MockRead data_reads[] = {
15004 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15005 MockRead("hello world"),
15006 MockRead(SYNCHRONOUS, OK),
15007 };
15008 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15009 arraysize(data_writes));
15010 session_deps_.socket_factory->AddSocketDataProvider(&data);
15011
15012 TestCompletionCallback callback;
15013
15014 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15015 EXPECT_EQ(ERR_IO_PENDING, rv);
15016
15017 rv = callback.WaitForResult();
15018 EXPECT_EQ(OK, rv);
15019
15020 const HttpResponseInfo* response = trans->GetResponseInfo();
15021 ASSERT_TRUE(response != NULL);
15022
15023 EXPECT_TRUE(response->headers.get() != NULL);
15024 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15025
15026 std::string response_data;
15027 rv = ReadTransaction(trans.get(), &response_data);
15028 EXPECT_EQ(OK, rv);
15029 EXPECT_EQ("hello world", response_data);
15030}
15031
15032// This test makes sure the retry logic doesn't trigger when reading an error
15033// response from a server that rejected a POST with a CONNECTION_RESET.
15034TEST_P(HttpNetworkTransactionTest,
15035 PostReadsErrorResponseAfterResetOnReusedSocket) {
mmenkee65e7af2015-10-13 17:16:4215036 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415037 MockWrite data_writes[] = {
15038 MockWrite("GET / HTTP/1.1\r\n"
15039 "Host: www.foo.com\r\n"
15040 "Connection: keep-alive\r\n\r\n"),
15041 MockWrite("POST / HTTP/1.1\r\n"
15042 "Host: www.foo.com\r\n"
15043 "Connection: keep-alive\r\n"
15044 "Content-Length: 3\r\n\r\n"),
15045 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15046 };
15047
15048 MockRead data_reads[] = {
15049 MockRead("HTTP/1.1 200 Peachy\r\n"
15050 "Content-Length: 14\r\n\r\n"),
15051 MockRead("first response"),
15052 MockRead("HTTP/1.1 400 Not OK\r\n"
15053 "Content-Length: 15\r\n\r\n"),
15054 MockRead("second response"),
15055 MockRead(SYNCHRONOUS, OK),
15056 };
15057 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15058 arraysize(data_writes));
15059 session_deps_.socket_factory->AddSocketDataProvider(&data);
15060
15061 TestCompletionCallback callback;
15062 HttpRequestInfo request1;
15063 request1.method = "GET";
15064 request1.url = GURL("http://www.foo.com/");
15065 request1.load_flags = 0;
15066
15067 scoped_ptr<HttpTransaction> trans1(
dcheng48459ac22014-08-26 00:46:4115068 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415069 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
15070 EXPECT_EQ(ERR_IO_PENDING, rv);
15071
15072 rv = callback.WaitForResult();
15073 EXPECT_EQ(OK, rv);
15074
15075 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
15076 ASSERT_TRUE(response1 != NULL);
15077
15078 EXPECT_TRUE(response1->headers.get() != NULL);
15079 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
15080
15081 std::string response_data1;
15082 rv = ReadTransaction(trans1.get(), &response_data1);
15083 EXPECT_EQ(OK, rv);
15084 EXPECT_EQ("first response", response_data1);
15085 // Delete the transaction to release the socket back into the socket pool.
15086 trans1.reset();
15087
olli.raula6df48b2a2015-11-26 07:40:2215088 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15089 element_readers.push_back(
15090 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15091 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415092
15093 HttpRequestInfo request2;
15094 request2.method = "POST";
15095 request2.url = GURL("http://www.foo.com/");
15096 request2.upload_data_stream = &upload_data_stream;
15097 request2.load_flags = 0;
15098
15099 scoped_ptr<HttpTransaction> trans2(
dcheng48459ac22014-08-26 00:46:4115100 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415101 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
15102 EXPECT_EQ(ERR_IO_PENDING, rv);
15103
15104 rv = callback.WaitForResult();
15105 EXPECT_EQ(OK, rv);
15106
15107 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
15108 ASSERT_TRUE(response2 != NULL);
15109
15110 EXPECT_TRUE(response2->headers.get() != NULL);
15111 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
15112
15113 std::string response_data2;
15114 rv = ReadTransaction(trans2.get(), &response_data2);
15115 EXPECT_EQ(OK, rv);
15116 EXPECT_EQ("second response", response_data2);
15117}
15118
15119TEST_P(HttpNetworkTransactionTest,
15120 PostReadsErrorResponseAfterResetPartialBodySent) {
olli.raula6df48b2a2015-11-26 07:40:2215121 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15122 element_readers.push_back(
15123 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15124 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415125
15126 HttpRequestInfo request;
15127 request.method = "POST";
15128 request.url = GURL("http://www.foo.com/");
15129 request.upload_data_stream = &upload_data_stream;
15130 request.load_flags = 0;
15131
mmenkee65e7af2015-10-13 17:16:4215132 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415133 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115134 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415135 // Send headers successfully, but get an error while sending the body.
15136 MockWrite data_writes[] = {
15137 MockWrite("POST / HTTP/1.1\r\n"
15138 "Host: www.foo.com\r\n"
15139 "Connection: keep-alive\r\n"
15140 "Content-Length: 3\r\n\r\n"
15141 "fo"),
15142 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15143 };
15144
15145 MockRead data_reads[] = {
15146 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15147 MockRead("hello world"),
15148 MockRead(SYNCHRONOUS, OK),
15149 };
15150 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15151 arraysize(data_writes));
15152 session_deps_.socket_factory->AddSocketDataProvider(&data);
15153
15154 TestCompletionCallback callback;
15155
15156 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15157 EXPECT_EQ(ERR_IO_PENDING, rv);
15158
15159 rv = callback.WaitForResult();
15160 EXPECT_EQ(OK, rv);
15161
15162 const HttpResponseInfo* response = trans->GetResponseInfo();
15163 ASSERT_TRUE(response != NULL);
15164
15165 EXPECT_TRUE(response->headers.get() != NULL);
15166 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15167
15168 std::string response_data;
15169 rv = ReadTransaction(trans.get(), &response_data);
15170 EXPECT_EQ(OK, rv);
15171 EXPECT_EQ("hello world", response_data);
15172}
15173
15174// This tests the more common case than the previous test, where headers and
15175// body are not merged into a single request.
15176TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0715177 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5415178
15179 HttpRequestInfo request;
15180 request.method = "POST";
15181 request.url = GURL("http://www.foo.com/");
15182 request.upload_data_stream = &upload_data_stream;
15183 request.load_flags = 0;
15184
mmenkee65e7af2015-10-13 17:16:4215185 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415186 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115187 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415188 // Send headers successfully, but get an error while sending the body.
15189 MockWrite data_writes[] = {
15190 MockWrite("POST / HTTP/1.1\r\n"
15191 "Host: www.foo.com\r\n"
15192 "Connection: keep-alive\r\n"
15193 "Transfer-Encoding: chunked\r\n\r\n"),
15194 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15195 };
15196
15197 MockRead data_reads[] = {
15198 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15199 MockRead("hello world"),
15200 MockRead(SYNCHRONOUS, OK),
15201 };
15202 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15203 arraysize(data_writes));
15204 session_deps_.socket_factory->AddSocketDataProvider(&data);
15205
15206 TestCompletionCallback callback;
15207
15208 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15209 EXPECT_EQ(ERR_IO_PENDING, rv);
15210 // Make sure the headers are sent before adding a chunk. This ensures that
15211 // they can't be merged with the body in a single send. Not currently
15212 // necessary since a chunked body is never merged with headers, but this makes
15213 // the test more future proof.
15214 base::RunLoop().RunUntilIdle();
15215
mmenkecbc2b712014-10-09 20:29:0715216 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5415217
15218 rv = callback.WaitForResult();
15219 EXPECT_EQ(OK, rv);
15220
15221 const HttpResponseInfo* response = trans->GetResponseInfo();
15222 ASSERT_TRUE(response != NULL);
15223
15224 EXPECT_TRUE(response->headers.get() != NULL);
15225 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15226
15227 std::string response_data;
15228 rv = ReadTransaction(trans.get(), &response_data);
15229 EXPECT_EQ(OK, rv);
15230 EXPECT_EQ("hello world", response_data);
15231}
15232
15233TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
olli.raula6df48b2a2015-11-26 07:40:2215234 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15235 element_readers.push_back(
15236 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15237 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415238
15239 HttpRequestInfo request;
15240 request.method = "POST";
15241 request.url = GURL("http://www.foo.com/");
15242 request.upload_data_stream = &upload_data_stream;
15243 request.load_flags = 0;
15244
mmenkee65e7af2015-10-13 17:16:4215245 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415246 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115247 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415248
15249 MockWrite data_writes[] = {
15250 MockWrite("POST / HTTP/1.1\r\n"
15251 "Host: www.foo.com\r\n"
15252 "Connection: keep-alive\r\n"
15253 "Content-Length: 3\r\n\r\n"),
15254 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15255 };
15256
15257 MockRead data_reads[] = {
15258 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
15259 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15260 MockRead("hello world"),
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());
15270 EXPECT_EQ(ERR_IO_PENDING, rv);
15271
15272 rv = callback.WaitForResult();
15273 EXPECT_EQ(OK, rv);
15274
15275 const HttpResponseInfo* response = trans->GetResponseInfo();
15276 ASSERT_TRUE(response != NULL);
15277
15278 EXPECT_TRUE(response->headers.get() != NULL);
15279 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15280
15281 std::string response_data;
15282 rv = ReadTransaction(trans.get(), &response_data);
15283 EXPECT_EQ(OK, rv);
15284 EXPECT_EQ("hello world", response_data);
15285}
15286
15287TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215288 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15289 element_readers.push_back(
15290 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15291 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415292
15293 HttpRequestInfo request;
15294 request.method = "POST";
15295 request.url = GURL("http://www.foo.com/");
15296 request.upload_data_stream = &upload_data_stream;
15297 request.load_flags = 0;
15298
mmenkee65e7af2015-10-13 17:16:4215299 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415300 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115301 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415302 // Send headers successfully, but get an error while sending the body.
15303 MockWrite data_writes[] = {
15304 MockWrite("POST / HTTP/1.1\r\n"
15305 "Host: www.foo.com\r\n"
15306 "Connection: keep-alive\r\n"
15307 "Content-Length: 3\r\n\r\n"),
15308 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15309 };
15310
15311 MockRead data_reads[] = {
15312 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
15313 MockRead("hello world"),
15314 MockRead(SYNCHRONOUS, OK),
15315 };
15316 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15317 arraysize(data_writes));
15318 session_deps_.socket_factory->AddSocketDataProvider(&data);
15319
15320 TestCompletionCallback callback;
15321
15322 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15323 EXPECT_EQ(ERR_IO_PENDING, rv);
15324
15325 rv = callback.WaitForResult();
15326 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415327}
15328
15329TEST_P(HttpNetworkTransactionTest,
15330 PostIgnoresNonErrorResponseAfterResetAnd100) {
olli.raula6df48b2a2015-11-26 07:40:2215331 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15332 element_readers.push_back(
15333 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15334 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415335
15336 HttpRequestInfo request;
15337 request.method = "POST";
15338 request.url = GURL("http://www.foo.com/");
15339 request.upload_data_stream = &upload_data_stream;
15340 request.load_flags = 0;
15341
mmenkee65e7af2015-10-13 17:16:4215342 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415343 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115344 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415345 // Send headers successfully, but get an error while sending the body.
15346 MockWrite data_writes[] = {
15347 MockWrite("POST / HTTP/1.1\r\n"
15348 "Host: www.foo.com\r\n"
15349 "Connection: keep-alive\r\n"
15350 "Content-Length: 3\r\n\r\n"),
15351 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15352 };
15353
15354 MockRead data_reads[] = {
15355 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
15356 MockRead("HTTP/1.0 302 Redirect\r\n"),
15357 MockRead("Location: http://somewhere-else.com/\r\n"),
15358 MockRead("Content-Length: 0\r\n\r\n"),
15359 MockRead(SYNCHRONOUS, OK),
15360 };
15361 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15362 arraysize(data_writes));
15363 session_deps_.socket_factory->AddSocketDataProvider(&data);
15364
15365 TestCompletionCallback callback;
15366
15367 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15368 EXPECT_EQ(ERR_IO_PENDING, rv);
15369
15370 rv = callback.WaitForResult();
15371 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415372}
15373
15374TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215375 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15376 element_readers.push_back(
15377 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15378 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415379
15380 HttpRequestInfo request;
15381 request.method = "POST";
15382 request.url = GURL("http://www.foo.com/");
15383 request.upload_data_stream = &upload_data_stream;
15384 request.load_flags = 0;
15385
mmenkee65e7af2015-10-13 17:16:4215386 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415387 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115388 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415389 // Send headers successfully, but get an error while sending the body.
15390 MockWrite data_writes[] = {
15391 MockWrite("POST / HTTP/1.1\r\n"
15392 "Host: www.foo.com\r\n"
15393 "Connection: keep-alive\r\n"
15394 "Content-Length: 3\r\n\r\n"),
15395 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15396 };
15397
15398 MockRead data_reads[] = {
15399 MockRead("HTTP 0.9 rocks!"),
15400 MockRead(SYNCHRONOUS, OK),
15401 };
15402 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15403 arraysize(data_writes));
15404 session_deps_.socket_factory->AddSocketDataProvider(&data);
15405
15406 TestCompletionCallback callback;
15407
15408 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15409 EXPECT_EQ(ERR_IO_PENDING, rv);
15410
15411 rv = callback.WaitForResult();
15412 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415413}
15414
15415TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215416 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15417 element_readers.push_back(
15418 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15419 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415420
15421 HttpRequestInfo request;
15422 request.method = "POST";
15423 request.url = GURL("http://www.foo.com/");
15424 request.upload_data_stream = &upload_data_stream;
15425 request.load_flags = 0;
15426
mmenkee65e7af2015-10-13 17:16:4215427 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415428 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115429 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415430 // Send headers successfully, but get an error while sending the body.
15431 MockWrite data_writes[] = {
15432 MockWrite("POST / HTTP/1.1\r\n"
15433 "Host: www.foo.com\r\n"
15434 "Connection: keep-alive\r\n"
15435 "Content-Length: 3\r\n\r\n"),
15436 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15437 };
15438
15439 MockRead data_reads[] = {
15440 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
15441 MockRead(SYNCHRONOUS, OK),
15442 };
15443 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15444 arraysize(data_writes));
15445 session_deps_.socket_factory->AddSocketDataProvider(&data);
15446
15447 TestCompletionCallback callback;
15448
15449 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15450 EXPECT_EQ(ERR_IO_PENDING, rv);
15451
15452 rv = callback.WaitForResult();
15453 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415454}
15455
Adam Rice425cf122015-01-19 06:18:2415456// Verify that proxy headers are not sent to the destination server when
15457// establishing a tunnel for a secure WebSocket connection.
15458TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
15459 HttpRequestInfo request;
15460 request.method = "GET";
bncce36dca22015-04-21 22:11:2315461 request.url = GURL("wss://www.example.org/");
Adam Rice425cf122015-01-19 06:18:2415462 AddWebSocketHeaders(&request.extra_headers);
15463
15464 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:0315465 session_deps_.proxy_service =
15466 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
Adam Rice425cf122015-01-19 06:18:2415467
mmenkee65e7af2015-10-13 17:16:4215468 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2415469
15470 // Since a proxy is configured, try to establish a tunnel.
15471 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1715472 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15473 "Host: www.example.org:443\r\n"
15474 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415475
15476 // After calling trans->RestartWithAuth(), this is the request we should
15477 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1715478 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15479 "Host: www.example.org:443\r\n"
15480 "Proxy-Connection: keep-alive\r\n"
15481 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415482
rsleevidb16bb02015-11-12 23:47:1715483 MockWrite("GET / HTTP/1.1\r\n"
15484 "Host: www.example.org\r\n"
15485 "Connection: Upgrade\r\n"
15486 "Upgrade: websocket\r\n"
15487 "Origin: http://www.example.org\r\n"
15488 "Sec-WebSocket-Version: 13\r\n"
15489 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415490 };
15491
15492 // The proxy responds to the connect with a 407, using a persistent
15493 // connection.
15494 MockRead data_reads[] = {
15495 // No credentials.
15496 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
15497 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
mmenkee71e15332015-10-07 16:39:5415498 MockRead("Content-Length: 0\r\n"),
15499 MockRead("Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415500
15501 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15502
15503 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15504 MockRead("Upgrade: websocket\r\n"),
15505 MockRead("Connection: Upgrade\r\n"),
15506 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15507 };
15508
15509 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15510 arraysize(data_writes));
15511 session_deps_.socket_factory->AddSocketDataProvider(&data);
15512 SSLSocketDataProvider ssl(ASYNC, OK);
15513 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15514
15515 scoped_ptr<HttpTransaction> trans(
15516 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15517 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15518 trans->SetWebSocketHandshakeStreamCreateHelper(
15519 &websocket_stream_create_helper);
15520
15521 {
15522 TestCompletionCallback callback;
15523
15524 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15525 EXPECT_EQ(ERR_IO_PENDING, rv);
15526
15527 rv = callback.WaitForResult();
15528 EXPECT_EQ(OK, rv);
15529 }
15530
15531 const HttpResponseInfo* response = trans->GetResponseInfo();
15532 ASSERT_TRUE(response);
15533 ASSERT_TRUE(response->headers.get());
15534 EXPECT_EQ(407, response->headers->response_code());
15535
15536 {
15537 TestCompletionCallback callback;
15538
15539 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
15540 callback.callback());
15541 EXPECT_EQ(ERR_IO_PENDING, rv);
15542
15543 rv = callback.WaitForResult();
15544 EXPECT_EQ(OK, rv);
15545 }
15546
15547 response = trans->GetResponseInfo();
15548 ASSERT_TRUE(response);
15549 ASSERT_TRUE(response->headers.get());
15550
15551 EXPECT_EQ(101, response->headers->response_code());
15552
15553 trans.reset();
15554 session->CloseAllConnections();
15555}
15556
15557// Verify that proxy headers are not sent to the destination server when
15558// establishing a tunnel for an insecure WebSocket connection.
15559// This requires the authentication info to be injected into the auth cache
15560// due to crbug.com/395064
15561// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
15562TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
15563 HttpRequestInfo request;
15564 request.method = "GET";
bncce36dca22015-04-21 22:11:2315565 request.url = GURL("ws://www.example.org/");
Adam Rice425cf122015-01-19 06:18:2415566 AddWebSocketHeaders(&request.extra_headers);
15567
15568 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:0315569 session_deps_.proxy_service =
15570 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
Adam Rice425cf122015-01-19 06:18:2415571
mmenkee65e7af2015-10-13 17:16:4215572 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2415573
15574 MockWrite data_writes[] = {
15575 // Try to establish a tunnel for the WebSocket connection, with
15576 // credentials. Because WebSockets have a separate set of socket pools,
15577 // they cannot and will not use the same TCP/IP connection as the
15578 // preflight HTTP request.
15579 MockWrite(
bncce36dca22015-04-21 22:11:2315580 "CONNECT www.example.org:80 HTTP/1.1\r\n"
15581 "Host: www.example.org:80\r\n"
Adam Rice425cf122015-01-19 06:18:2415582 "Proxy-Connection: keep-alive\r\n"
15583 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
15584
15585 MockWrite(
15586 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2315587 "Host: www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415588 "Connection: Upgrade\r\n"
15589 "Upgrade: websocket\r\n"
bncce36dca22015-04-21 22:11:2315590 "Origin: http://www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415591 "Sec-WebSocket-Version: 13\r\n"
15592 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
15593 };
15594
15595 MockRead data_reads[] = {
15596 // HTTP CONNECT with credentials.
15597 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15598
15599 // WebSocket connection established inside tunnel.
15600 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15601 MockRead("Upgrade: websocket\r\n"),
15602 MockRead("Connection: Upgrade\r\n"),
15603 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15604 };
15605
15606 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15607 arraysize(data_writes));
15608 session_deps_.socket_factory->AddSocketDataProvider(&data);
15609
15610 session->http_auth_cache()->Add(
15611 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
15612 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
15613
15614 scoped_ptr<HttpTransaction> trans(
15615 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15616 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15617 trans->SetWebSocketHandshakeStreamCreateHelper(
15618 &websocket_stream_create_helper);
15619
15620 TestCompletionCallback callback;
15621
15622 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15623 EXPECT_EQ(ERR_IO_PENDING, rv);
15624
15625 rv = callback.WaitForResult();
15626 EXPECT_EQ(OK, rv);
15627
15628 const HttpResponseInfo* response = trans->GetResponseInfo();
15629 ASSERT_TRUE(response);
15630 ASSERT_TRUE(response->headers.get());
15631
15632 EXPECT_EQ(101, response->headers->response_code());
15633
15634 trans.reset();
15635 session->CloseAllConnections();
15636}
15637
sclittlefb249892015-09-10 21:33:2215638TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
olli.raula6df48b2a2015-11-26 07:40:2215639 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15640 element_readers.push_back(
15641 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15642 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2215643
15644 HttpRequestInfo request;
15645 request.method = "POST";
15646 request.url = GURL("http://www.foo.com/");
15647 request.upload_data_stream = &upload_data_stream;
15648
mmenkee65e7af2015-10-13 17:16:4215649 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215650 scoped_ptr<HttpTransaction> trans(
15651 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15652 MockWrite data_writes[] = {
15653 MockWrite("POST / HTTP/1.1\r\n"
15654 "Host: www.foo.com\r\n"
15655 "Connection: keep-alive\r\n"
15656 "Content-Length: 3\r\n\r\n"),
15657 MockWrite("foo"),
15658 };
15659
15660 MockRead data_reads[] = {
15661 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15662 MockRead(SYNCHRONOUS, OK),
15663 };
15664 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15665 arraysize(data_writes));
15666 session_deps_.socket_factory->AddSocketDataProvider(&data);
15667
15668 TestCompletionCallback callback;
15669
15670 EXPECT_EQ(ERR_IO_PENDING,
15671 trans->Start(&request, callback.callback(), BoundNetLog()));
15672 EXPECT_EQ(OK, callback.WaitForResult());
15673
15674 std::string response_data;
15675 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15676
15677 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15678 trans->GetTotalSentBytes());
15679 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15680 trans->GetTotalReceivedBytes());
15681}
15682
15683TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
olli.raula6df48b2a2015-11-26 07:40:2215684 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15685 element_readers.push_back(
15686 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15687 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2215688
15689 HttpRequestInfo request;
15690 request.method = "POST";
15691 request.url = GURL("http://www.foo.com/");
15692 request.upload_data_stream = &upload_data_stream;
15693
mmenkee65e7af2015-10-13 17:16:4215694 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215695 scoped_ptr<HttpTransaction> trans(
15696 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15697 MockWrite data_writes[] = {
15698 MockWrite("POST / HTTP/1.1\r\n"
15699 "Host: www.foo.com\r\n"
15700 "Connection: keep-alive\r\n"
15701 "Content-Length: 3\r\n\r\n"),
15702 MockWrite("foo"),
15703 };
15704
15705 MockRead data_reads[] = {
15706 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
15707 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15708 MockRead(SYNCHRONOUS, OK),
15709 };
15710 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15711 arraysize(data_writes));
15712 session_deps_.socket_factory->AddSocketDataProvider(&data);
15713
15714 TestCompletionCallback callback;
15715
15716 EXPECT_EQ(ERR_IO_PENDING,
15717 trans->Start(&request, callback.callback(), BoundNetLog()));
15718 EXPECT_EQ(OK, callback.WaitForResult());
15719
15720 std::string response_data;
15721 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15722
15723 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15724 trans->GetTotalSentBytes());
15725 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15726 trans->GetTotalReceivedBytes());
15727}
15728
15729TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2215730 ChunkedUploadDataStream upload_data_stream(0);
15731
15732 HttpRequestInfo request;
15733 request.method = "POST";
15734 request.url = GURL("http://www.foo.com/");
15735 request.upload_data_stream = &upload_data_stream;
15736
mmenkee65e7af2015-10-13 17:16:4215737 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215738 scoped_ptr<HttpTransaction> trans(
15739 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15740 // Send headers successfully, but get an error while sending the body.
15741 MockWrite data_writes[] = {
15742 MockWrite("POST / HTTP/1.1\r\n"
15743 "Host: www.foo.com\r\n"
15744 "Connection: keep-alive\r\n"
15745 "Transfer-Encoding: chunked\r\n\r\n"),
15746 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
15747 };
15748
15749 MockRead data_reads[] = {
15750 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15751 MockRead(SYNCHRONOUS, OK),
15752 };
15753 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15754 arraysize(data_writes));
15755 session_deps_.socket_factory->AddSocketDataProvider(&data);
15756
15757 TestCompletionCallback callback;
15758
15759 EXPECT_EQ(ERR_IO_PENDING,
15760 trans->Start(&request, callback.callback(), BoundNetLog()));
15761
15762 base::RunLoop().RunUntilIdle();
15763 upload_data_stream.AppendData("f", 1, false);
15764
15765 base::RunLoop().RunUntilIdle();
15766 upload_data_stream.AppendData("oo", 2, true);
15767
15768 EXPECT_EQ(OK, callback.WaitForResult());
15769
15770 std::string response_data;
15771 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15772
15773 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15774 trans->GetTotalSentBytes());
15775 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15776 trans->GetTotalReceivedBytes());
15777}
15778
bncf4588402015-11-24 13:33:1815779TEST_P(HttpNetworkTransactionTest, EnableNPN) {
15780 session_deps_.next_protos = NextProtosDefaults();
15781 session_deps_.enable_npn = true;
15782
15783 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15784 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15785
15786 EXPECT_THAT(trans.server_ssl_config_.alpn_protos,
15787 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15788 EXPECT_THAT(trans.server_ssl_config_.npn_protos,
15789 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15790}
15791
15792TEST_P(HttpNetworkTransactionTest, DisableNPN) {
15793 session_deps_.next_protos = NextProtosDefaults();
15794 session_deps_.enable_npn = false;
15795
15796 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15797 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15798
15799 EXPECT_THAT(trans.server_ssl_config_.alpn_protos,
15800 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15801 EXPECT_TRUE(trans.server_ssl_config_.npn_protos.empty());
15802}
15803
[email protected]89ceba9a2009-03-21 03:46:0615804} // namespace net