blob: 8ff5a2fa822c2f94bb257d4f0cbed17a259ea749 [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[] = {
1090 MockRead("HTTP/1.1 404 Not Found\r\n"),
1091 MockRead("Server: Blah\r\n"),
1092 MockRead("Content-Length: 1234\r\n\r\n"),
1093
1094 // No response body because the test stops reading here.
[email protected]8ddf8322012-02-23 18:08:061095 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:231096 };
1097
[email protected]31a2bfe2010-02-09 08:03:391098 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1099 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:071100 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231101
[email protected]49639fa2011-12-20 23:22:411102 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231103
[email protected]49639fa2011-12-20 23:22:411104 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421105 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:231106
1107 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421108 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:231109
[email protected]1c773ea12009-04-28 19:58:421110 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501111 ASSERT_TRUE(response != NULL);
[email protected]ef0faf2e72009-03-05 23:27:231112
1113 // Check that the headers got parsed.
[email protected]90499482013-06-01 00:39:501114 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]ef0faf2e72009-03-05 23:27:231115 EXPECT_EQ(1234, response->headers->GetContentLength());
1116 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151117 EXPECT_TRUE(response->proxy_server.IsEmpty());
[email protected]597a1ab2014-06-26 08:12:271118 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
[email protected]ef0faf2e72009-03-05 23:27:231119
1120 std::string server_header;
1121 void* iter = NULL;
1122 bool has_server_header = response->headers->EnumerateHeader(
1123 &iter, "Server", &server_header);
1124 EXPECT_TRUE(has_server_header);
1125 EXPECT_EQ("Blah", server_header);
1126
1127 // Reading should give EOF right away, since there is no message body
1128 // (despite non-zero content-length).
1129 std::string response_data;
1130 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421131 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:231132 EXPECT_EQ("", response_data);
1133}
1134
[email protected]23e482282013-06-14 16:08:021135TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
mmenkee65e7af2015-10-13 17:16:421136 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521137
1138 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351139 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1140 MockRead("hello"),
1141 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1142 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061143 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521144 };
[email protected]31a2bfe2010-02-09 08:03:391145 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071146 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521147
[email protected]0b0bf032010-09-21 18:08:501148 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521149 "hello", "world"
1150 };
1151
1152 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421153 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521154 request.method = "GET";
bncce36dca22015-04-21 22:11:231155 request.url = GURL("http://www.example.org/");
initial.commit586acc5fe2008-07-26 22:42:521156 request.load_flags = 0;
1157
[email protected]262eec82013-03-19 21:01:361158 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501159 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271160
[email protected]49639fa2011-12-20 23:22:411161 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521162
[email protected]49639fa2011-12-20 23:22:411163 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421164 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521165
1166 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421167 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521168
[email protected]1c773ea12009-04-28 19:58:421169 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501170 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521171
[email protected]90499482013-06-01 00:39:501172 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251173 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151174 EXPECT_TRUE(response->proxy_server.IsEmpty());
initial.commit586acc5fe2008-07-26 22:42:521175
1176 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571177 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421178 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251179 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521180 }
1181}
1182
[email protected]23e482282013-06-14 16:08:021183TEST_P(HttpNetworkTransactionTest, Ignores100) {
olli.raula6df48b2a2015-11-26 07:40:221184 std::vector<scoped_ptr<UploadElementReader>> element_readers;
1185 element_readers.push_back(
1186 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
1187 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271188
[email protected]1c773ea12009-04-28 19:58:421189 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521190 request.method = "POST";
1191 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271192 request.upload_data_stream = &upload_data_stream;
initial.commit586acc5fe2008-07-26 22:42:521193 request.load_flags = 0;
1194
mmenkee65e7af2015-10-13 17:16:421195 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271196 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411197 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271198
initial.commit586acc5fe2008-07-26 22:42:521199 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351200 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1201 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1202 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061203 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521204 };
[email protected]31a2bfe2010-02-09 08:03:391205 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071206 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521207
[email protected]49639fa2011-12-20 23:22:411208 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521209
[email protected]49639fa2011-12-20 23:22:411210 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421211 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521212
1213 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421214 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521215
[email protected]1c773ea12009-04-28 19:58:421216 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501217 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521218
[email protected]90499482013-06-01 00:39:501219 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251220 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521221
1222 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571223 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421224 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251225 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521226}
1227
[email protected]3a2d3662009-03-27 03:49:141228// This test is almost the same as Ignores100 above, but the response contains
1229// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571230// HTTP/1.1 and the two status headers are read in one read.
[email protected]23e482282013-06-14 16:08:021231TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421232 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141233 request.method = "GET";
1234 request.url = GURL("http://www.foo.com/");
1235 request.load_flags = 0;
1236
mmenkee65e7af2015-10-13 17:16:421237 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271238 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411239 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271240
[email protected]3a2d3662009-03-27 03:49:141241 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571242 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1243 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141244 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061245 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141246 };
[email protected]31a2bfe2010-02-09 08:03:391247 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071248 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141249
[email protected]49639fa2011-12-20 23:22:411250 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141251
[email protected]49639fa2011-12-20 23:22:411252 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421253 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:141254
1255 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421256 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:141257
[email protected]1c773ea12009-04-28 19:58:421258 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501259 ASSERT_TRUE(response != NULL);
[email protected]3a2d3662009-03-27 03:49:141260
[email protected]90499482013-06-01 00:39:501261 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3a2d3662009-03-27 03:49:141262 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1263
1264 std::string response_data;
1265 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421266 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:141267 EXPECT_EQ("hello world", response_data);
1268}
1269
[email protected]23e482282013-06-14 16:08:021270TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081271 HttpRequestInfo request;
1272 request.method = "POST";
1273 request.url = GURL("http://www.foo.com/");
1274 request.load_flags = 0;
1275
mmenkee65e7af2015-10-13 17:16:421276 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
zmo9528c9f42015-08-04 22:12:081277 scoped_ptr<HttpTransaction> trans(
1278 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1279
1280 MockRead data_reads[] = {
1281 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1282 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381283 };
zmo9528c9f42015-08-04 22:12:081284 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1285 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381286
zmo9528c9f42015-08-04 22:12:081287 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381288
zmo9528c9f42015-08-04 22:12:081289 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1290 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ee9410e72010-01-07 01:42:381291
zmo9528c9f42015-08-04 22:12:081292 rv = callback.WaitForResult();
1293 EXPECT_EQ(OK, rv);
[email protected]ee9410e72010-01-07 01:42:381294
zmo9528c9f42015-08-04 22:12:081295 std::string response_data;
1296 rv = ReadTransaction(trans.get(), &response_data);
1297 EXPECT_EQ(OK, rv);
1298 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381299}
1300
[email protected]23e482282013-06-14 16:08:021301TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381302 HttpRequestInfo request;
1303 request.method = "POST";
1304 request.url = GURL("http://www.foo.com/");
1305 request.load_flags = 0;
1306
mmenkee65e7af2015-10-13 17:16:421307 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271308 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411309 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271310
[email protected]ee9410e72010-01-07 01:42:381311 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061312 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381313 };
[email protected]31a2bfe2010-02-09 08:03:391314 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071315 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381316
[email protected]49639fa2011-12-20 23:22:411317 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381318
[email protected]49639fa2011-12-20 23:22:411319 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:381320 EXPECT_EQ(ERR_IO_PENDING, rv);
1321
1322 rv = callback.WaitForResult();
1323 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1324}
1325
[email protected]23e482282013-06-14 16:08:021326void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511327 const MockWrite* write_failure,
1328 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421329 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521330 request.method = "GET";
1331 request.url = GURL("http://www.foo.com/");
1332 request.load_flags = 0;
1333
vishal.b62985ca92015-04-17 08:45:511334 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071335 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421336 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271337
[email protected]202965992011-12-07 23:04:511338 // Written data for successfully sending both requests.
1339 MockWrite data1_writes[] = {
1340 MockWrite("GET / HTTP/1.1\r\n"
1341 "Host: www.foo.com\r\n"
1342 "Connection: keep-alive\r\n\r\n"),
1343 MockWrite("GET / HTTP/1.1\r\n"
1344 "Host: www.foo.com\r\n"
1345 "Connection: keep-alive\r\n\r\n")
1346 };
1347
1348 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521349 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351350 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1351 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061352 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521353 };
[email protected]202965992011-12-07 23:04:511354
1355 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491356 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511357 data1_writes[1] = *write_failure;
1358 } else {
1359 ASSERT_TRUE(read_failure);
1360 data1_reads[2] = *read_failure;
1361 }
1362
1363 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1364 data1_writes, arraysize(data1_writes));
[email protected]bb88e1d32013-05-03 23:11:071365 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521366
1367 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351368 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1369 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061370 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521371 };
[email protected]31a2bfe2010-02-09 08:03:391372 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071373 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521374
thestig9d3bb0c2015-01-24 00:49:511375 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521376 "hello", "world"
1377 };
1378
[email protected]58e32bb2013-01-21 18:23:251379 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521380 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411381 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521382
[email protected]262eec82013-03-19 21:01:361383 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501384 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
initial.commit586acc5fe2008-07-26 22:42:521385
[email protected]49639fa2011-12-20 23:22:411386 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421387 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521388
1389 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421390 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521391
[email protected]58e32bb2013-01-21 18:23:251392 LoadTimingInfo load_timing_info;
1393 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1394 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1395 if (i == 0) {
1396 first_socket_log_id = load_timing_info.socket_log_id;
1397 } else {
1398 // The second request should be using a new socket.
1399 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1400 }
1401
[email protected]1c773ea12009-04-28 19:58:421402 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501403 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521404
[email protected]90499482013-06-01 00:39:501405 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251406 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521407
1408 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571409 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421410 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251411 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521412 }
1413}
[email protected]3d2a59b2008-09-26 19:44:251414
[email protected]a34f61ee2014-03-18 20:59:491415void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1416 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101417 const MockRead* read_failure,
1418 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491419 HttpRequestInfo request;
1420 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101421 request.url = GURL("https://www.foo.com/");
[email protected]a34f61ee2014-03-18 20:59:491422 request.load_flags = 0;
1423
vishal.b62985ca92015-04-17 08:45:511424 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491425 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421426 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491427
[email protected]09356c652014-03-25 15:36:101428 SSLSocketDataProvider ssl1(ASYNC, OK);
1429 SSLSocketDataProvider ssl2(ASYNC, OK);
1430 if (use_spdy) {
rdsmithebb50aa2015-11-12 03:44:381431 ssl1.SetNextProto(GetProtocol());
1432 ssl2.SetNextProto(GetProtocol());
[email protected]09356c652014-03-25 15:36:101433 }
1434 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1435 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491436
[email protected]09356c652014-03-25 15:36:101437 // SPDY versions of the request and response.
1438 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1439 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1440 scoped_ptr<SpdyFrame> spdy_response(
1441 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1442 scoped_ptr<SpdyFrame> spdy_data(
1443 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
[email protected]a34f61ee2014-03-18 20:59:491444
[email protected]09356c652014-03-25 15:36:101445 // HTTP/1.1 versions of the request and response.
1446 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1447 "Host: www.foo.com\r\n"
1448 "Connection: keep-alive\r\n\r\n";
1449 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1450 const char kHttpData[] = "hello";
1451
1452 std::vector<MockRead> data1_reads;
1453 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491454 if (write_failure) {
1455 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101456 data1_writes.push_back(*write_failure);
1457 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491458 } else {
1459 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101460 if (use_spdy) {
1461 data1_writes.push_back(CreateMockWrite(*spdy_request));
1462 } else {
1463 data1_writes.push_back(MockWrite(kHttpRequest));
1464 }
1465 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491466 }
1467
[email protected]09356c652014-03-25 15:36:101468 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1469 &data1_writes[0], data1_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491470 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1471
[email protected]09356c652014-03-25 15:36:101472 std::vector<MockRead> data2_reads;
1473 std::vector<MockWrite> data2_writes;
1474
1475 if (use_spdy) {
1476 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1477
1478 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1479 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1480 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1481 } else {
1482 data2_writes.push_back(
1483 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1484
1485 data2_reads.push_back(
1486 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1487 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1488 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1489 }
rch8e6c6c42015-05-01 14:05:131490 SequencedSocketData data2(&data2_reads[0], data2_reads.size(),
1491 &data2_writes[0], data2_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491492 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1493
1494 // Preconnect a socket.
ttuttle859dc7a2015-04-23 19:42:291495 SSLConfig ssl_config;
[email protected]a34f61ee2014-03-18 20:59:491496 session->ssl_config_service()->GetSSLConfig(&ssl_config);
bnc1f295372015-10-21 23:24:221497 session->GetAlpnProtos(&ssl_config.alpn_protos);
1498 session->GetNpnProtos(&ssl_config.npn_protos);
mmenked1205bd3972015-07-15 22:26:351499 session->http_stream_factory()->PreconnectStreams(1, request, ssl_config,
1500 ssl_config);
[email protected]a34f61ee2014-03-18 20:59:491501 // Wait for the preconnect to complete.
1502 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1503 base::RunLoop().RunUntilIdle();
[email protected]09356c652014-03-25 15:36:101504 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491505
1506 // Make the request.
1507 TestCompletionCallback callback;
1508
1509 scoped_ptr<HttpTransaction> trans(
1510 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1511
1512 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1513 EXPECT_EQ(ERR_IO_PENDING, rv);
1514
1515 rv = callback.WaitForResult();
1516 EXPECT_EQ(OK, rv);
1517
1518 LoadTimingInfo load_timing_info;
1519 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101520 TestLoadTimingNotReused(
1521 load_timing_info,
1522 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491523
1524 const HttpResponseInfo* response = trans->GetResponseInfo();
1525 ASSERT_TRUE(response != NULL);
1526
1527 EXPECT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:021528 if (response->was_fetched_via_spdy) {
1529 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1530 } else {
1531 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1532 }
[email protected]a34f61ee2014-03-18 20:59:491533
1534 std::string response_data;
1535 rv = ReadTransaction(trans.get(), &response_data);
1536 EXPECT_EQ(OK, rv);
[email protected]09356c652014-03-25 15:36:101537 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491538}
1539
[email protected]23e482282013-06-14 16:08:021540TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:231541 KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061542 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]202965992011-12-07 23:04:511543 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1544}
1545
[email protected]23e482282013-06-14 16:08:021546TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061547 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]202965992011-12-07 23:04:511548 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251549}
1550
[email protected]23e482282013-06-14 16:08:021551TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061552 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]202965992011-12-07 23:04:511553 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251554}
1555
[email protected]d58ceea82014-06-04 10:55:541556// Make sure that on a 408 response (Request Timeout), the request is retried,
1557// if the socket was a reused keep alive socket.
1558TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1559 MockRead read_failure(SYNCHRONOUS,
1560 "HTTP/1.1 408 Request Timeout\r\n"
1561 "Connection: Keep-Alive\r\n"
1562 "Content-Length: 6\r\n\r\n"
1563 "Pickle");
1564 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1565}
1566
[email protected]a34f61ee2014-03-18 20:59:491567TEST_P(HttpNetworkTransactionTest,
1568 PreconnectErrorNotConnectedOnWrite) {
1569 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]09356c652014-03-25 15:36:101570 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
[email protected]a34f61ee2014-03-18 20:59:491571}
1572
1573TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1574 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]09356c652014-03-25 15:36:101575 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491576}
1577
1578TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1579 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]09356c652014-03-25 15:36:101580 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1581}
1582
1583TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1584 MockRead read_failure(ASYNC, OK); // EOF
1585 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1586}
1587
[email protected]d58ceea82014-06-04 10:55:541588// Make sure that on a 408 response (Request Timeout), the request is retried,
1589// if the socket was a preconnected (UNUSED_IDLE) socket.
1590TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1591 MockRead read_failure(SYNCHRONOUS,
1592 "HTTP/1.1 408 Request Timeout\r\n"
1593 "Connection: Keep-Alive\r\n"
1594 "Content-Length: 6\r\n\r\n"
1595 "Pickle");
1596 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1597 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1598}
1599
[email protected]09356c652014-03-25 15:36:101600TEST_P(HttpNetworkTransactionTest,
1601 SpdyPreconnectErrorNotConnectedOnWrite) {
1602 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1603 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1604}
1605
1606TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1607 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1608 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1609}
1610
1611TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1612 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1613 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1614}
1615
1616TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1617 MockRead read_failure(ASYNC, OK); // EOF
1618 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:491619}
1620
[email protected]23e482282013-06-14 16:08:021621TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421622 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251623 request.method = "GET";
bncce36dca22015-04-21 22:11:231624 request.url = GURL("http://www.example.org/");
[email protected]3d2a59b2008-09-26 19:44:251625 request.load_flags = 0;
1626
mmenkee65e7af2015-10-13 17:16:421627 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271628 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411629 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271630
[email protected]3d2a59b2008-09-26 19:44:251631 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061632 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:351633 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1634 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061635 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251636 };
[email protected]31a2bfe2010-02-09 08:03:391637 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071638 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:251639
[email protected]49639fa2011-12-20 23:22:411640 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:251641
[email protected]49639fa2011-12-20 23:22:411642 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421643 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:251644
1645 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421646 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
ttuttled9dbc652015-09-29 20:00:591647
1648 IPEndPoint endpoint;
1649 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
1650 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:251651}
1652
1653// What do various browsers do when the server closes a non-keepalive
1654// connection without sending any response header or body?
1655//
1656// IE7: error page
1657// Safari 3.1.2 (Windows): error page
1658// Firefox 3.0.1: blank page
1659// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:421660// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1661// Us: error page (EMPTY_RESPONSE)
[email protected]23e482282013-06-14 16:08:021662TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:251663 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061664 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:351665 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1666 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061667 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251668 };
[email protected]31a2bfe2010-02-09 08:03:391669 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1670 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:421671 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:251672}
[email protected]038e9a32008-10-08 22:40:161673
[email protected]1826a402014-01-08 15:40:481674// Test that network access can be deferred and resumed.
1675TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1676 HttpRequestInfo request;
1677 request.method = "GET";
bncce36dca22015-04-21 22:11:231678 request.url = GURL("http://www.example.org/");
[email protected]1826a402014-01-08 15:40:481679 request.load_flags = 0;
1680
mmenkee65e7af2015-10-13 17:16:421681 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1826a402014-01-08 15:40:481682 scoped_ptr<HttpTransaction> trans(
1683 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1684
1685 // Defer on OnBeforeNetworkStart.
1686 BeforeNetworkStartHandler net_start_handler(true); // defer
1687 trans->SetBeforeNetworkStartCallback(
1688 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1689 base::Unretained(&net_start_handler)));
1690
1691 MockRead data_reads[] = {
1692 MockRead("HTTP/1.0 200 OK\r\n"),
1693 MockRead("Content-Length: 5\r\n\r\n"),
1694 MockRead("hello"),
1695 MockRead(SYNCHRONOUS, 0),
1696 };
1697 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1698 session_deps_.socket_factory->AddSocketDataProvider(&data);
1699
1700 TestCompletionCallback callback;
1701
1702 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1703 EXPECT_EQ(ERR_IO_PENDING, rv);
1704 base::MessageLoop::current()->RunUntilIdle();
1705
1706 // Should have deferred for network start.
1707 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1708 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
[email protected]1826a402014-01-08 15:40:481709
1710 trans->ResumeNetworkStart();
1711 rv = callback.WaitForResult();
1712 EXPECT_EQ(OK, rv);
1713 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1714
1715 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1716 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1717 if (rv == ERR_IO_PENDING)
1718 rv = callback.WaitForResult();
1719 EXPECT_EQ(5, rv);
1720 trans.reset();
1721}
1722
1723// Test that network use can be deferred and canceled.
1724TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1725 HttpRequestInfo request;
1726 request.method = "GET";
bncce36dca22015-04-21 22:11:231727 request.url = GURL("http://www.example.org/");
[email protected]1826a402014-01-08 15:40:481728 request.load_flags = 0;
1729
mmenkee65e7af2015-10-13 17:16:421730 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1826a402014-01-08 15:40:481731 scoped_ptr<HttpTransaction> trans(
1732 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1733
1734 // Defer on OnBeforeNetworkStart.
1735 BeforeNetworkStartHandler net_start_handler(true); // defer
1736 trans->SetBeforeNetworkStartCallback(
1737 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1738 base::Unretained(&net_start_handler)));
1739
1740 TestCompletionCallback callback;
1741
1742 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1743 EXPECT_EQ(ERR_IO_PENDING, rv);
1744 base::MessageLoop::current()->RunUntilIdle();
1745
1746 // Should have deferred for network start.
1747 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1748 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
[email protected]1826a402014-01-08 15:40:481749}
1750
[email protected]7a5378b2012-11-04 03:25:171751// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1752// tests. There was a bug causing HttpNetworkTransaction to hang in the
1753// destructor in such situations.
1754// See http://crbug.com/154712 and http://crbug.com/156609.
[email protected]23e482282013-06-14 16:08:021755TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:171756 HttpRequestInfo request;
1757 request.method = "GET";
bncce36dca22015-04-21 22:11:231758 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171759 request.load_flags = 0;
1760
mmenkee65e7af2015-10-13 17:16:421761 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:361762 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501763 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171764
1765 MockRead data_reads[] = {
1766 MockRead("HTTP/1.0 200 OK\r\n"),
1767 MockRead("Connection: keep-alive\r\n"),
1768 MockRead("Content-Length: 100\r\n\r\n"),
1769 MockRead("hello"),
1770 MockRead(SYNCHRONOUS, 0),
1771 };
1772 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071773 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171774
1775 TestCompletionCallback callback;
1776
1777 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1778 EXPECT_EQ(ERR_IO_PENDING, rv);
1779
1780 rv = callback.WaitForResult();
1781 EXPECT_EQ(OK, rv);
1782
1783 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501784 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171785 if (rv == ERR_IO_PENDING)
1786 rv = callback.WaitForResult();
1787 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:501788 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171789 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1790
1791 trans.reset();
[email protected]2da659e2013-05-23 20:51:341792 base::MessageLoop::current()->RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171793 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1794}
1795
[email protected]23e482282013-06-14 16:08:021796TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:171797 HttpRequestInfo request;
1798 request.method = "GET";
bncce36dca22015-04-21 22:11:231799 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171800 request.load_flags = 0;
1801
mmenkee65e7af2015-10-13 17:16:421802 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:361803 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501804 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171805
1806 MockRead data_reads[] = {
1807 MockRead("HTTP/1.0 200 OK\r\n"),
1808 MockRead("Connection: keep-alive\r\n"),
1809 MockRead("Content-Length: 100\r\n\r\n"),
1810 MockRead(SYNCHRONOUS, 0),
1811 };
1812 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071813 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171814
1815 TestCompletionCallback callback;
1816
1817 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1818 EXPECT_EQ(ERR_IO_PENDING, rv);
1819
1820 rv = callback.WaitForResult();
1821 EXPECT_EQ(OK, rv);
1822
1823 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501824 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171825 if (rv == ERR_IO_PENDING)
1826 rv = callback.WaitForResult();
1827 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1828
1829 trans.reset();
[email protected]2da659e2013-05-23 20:51:341830 base::MessageLoop::current()->RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171831 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1832}
1833
[email protected]0b0bf032010-09-21 18:08:501834// Test that we correctly reuse a keep-alive connection after not explicitly
1835// reading the body.
[email protected]23e482282013-06-14 16:08:021836TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:131837 HttpRequestInfo request;
1838 request.method = "GET";
1839 request.url = GURL("http://www.foo.com/");
1840 request.load_flags = 0;
1841
vishal.b62985ca92015-04-17 08:45:511842 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071843 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421844 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271845
[email protected]0b0bf032010-09-21 18:08:501846 // Note that because all these reads happen in the same
1847 // StaticSocketDataProvider, it shows that the same socket is being reused for
1848 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:131849 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:501850 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1851 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:131852 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:501853 MockRead("HTTP/1.1 302 Found\r\n"
1854 "Content-Length: 0\r\n\r\n"),
1855 MockRead("HTTP/1.1 302 Found\r\n"
1856 "Content-Length: 5\r\n\r\n"
1857 "hello"),
1858 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1859 "Content-Length: 0\r\n\r\n"),
1860 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1861 "Content-Length: 5\r\n\r\n"
1862 "hello"),
[email protected]fc31d6a42010-06-24 18:05:131863 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1864 MockRead("hello"),
1865 };
1866 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071867 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]fc31d6a42010-06-24 18:05:131868
1869 MockRead data2_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061870 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
[email protected]fc31d6a42010-06-24 18:05:131871 };
1872 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071873 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]fc31d6a42010-06-24 18:05:131874
[email protected]0b0bf032010-09-21 18:08:501875 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1876 std::string response_lines[kNumUnreadBodies];
1877
[email protected]58e32bb2013-01-21 18:23:251878 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
[email protected]0b0bf032010-09-21 18:08:501879 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411880 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:131881
[email protected]262eec82013-03-19 21:01:361882 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501883 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]fc31d6a42010-06-24 18:05:131884
[email protected]49639fa2011-12-20 23:22:411885 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]fc31d6a42010-06-24 18:05:131886 EXPECT_EQ(ERR_IO_PENDING, rv);
1887
1888 rv = callback.WaitForResult();
1889 EXPECT_EQ(OK, rv);
1890
[email protected]58e32bb2013-01-21 18:23:251891 LoadTimingInfo load_timing_info;
1892 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1893 if (i == 0) {
1894 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1895 first_socket_log_id = load_timing_info.socket_log_id;
1896 } else {
1897 TestLoadTimingReused(load_timing_info);
1898 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1899 }
1900
[email protected]fc31d6a42010-06-24 18:05:131901 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:501902 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:131903
[email protected]90499482013-06-01 00:39:501904 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]0b0bf032010-09-21 18:08:501905 response_lines[i] = response->headers->GetStatusLine();
1906
1907 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:131908 }
[email protected]0b0bf032010-09-21 18:08:501909
1910 const char* const kStatusLines[] = {
1911 "HTTP/1.1 204 No Content",
1912 "HTTP/1.1 205 Reset Content",
1913 "HTTP/1.1 304 Not Modified",
1914 "HTTP/1.1 302 Found",
1915 "HTTP/1.1 302 Found",
1916 "HTTP/1.1 301 Moved Permanently",
1917 "HTTP/1.1 301 Moved Permanently",
1918 };
1919
mostynb91e0da982015-01-20 19:17:271920 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1921 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:501922
1923 for (int i = 0; i < kNumUnreadBodies; ++i)
1924 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1925
[email protected]49639fa2011-12-20 23:22:411926 TestCompletionCallback callback;
[email protected]262eec82013-03-19 21:01:361927 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501928 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:411929 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0b0bf032010-09-21 18:08:501930 EXPECT_EQ(ERR_IO_PENDING, rv);
1931 rv = callback.WaitForResult();
1932 EXPECT_EQ(OK, rv);
1933 const HttpResponseInfo* response = trans->GetResponseInfo();
1934 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:501935 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]0b0bf032010-09-21 18:08:501936 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1937 std::string response_data;
1938 rv = ReadTransaction(trans.get(), &response_data);
1939 EXPECT_EQ(OK, rv);
1940 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131941}
1942
[email protected]038e9a32008-10-08 22:40:161943// Test the request-challenge-retry sequence for basic auth.
1944// (basic auth is the easiest to mock, because it has no randomness).
[email protected]23e482282013-06-14 16:08:021945TEST_P(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421946 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161947 request.method = "GET";
bncce36dca22015-04-21 22:11:231948 request.url = GURL("http://www.example.org/");
[email protected]038e9a32008-10-08 22:40:161949 request.load_flags = 0;
1950
vishal.b62985ca92015-04-17 08:45:511951 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:071952 session_deps_.net_log = &log;
mmenkee65e7af2015-10-13 17:16:421953 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271954 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411955 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271956
[email protected]f9ee6b52008-11-08 06:46:231957 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:231958 MockWrite(
1959 "GET / HTTP/1.1\r\n"
1960 "Host: www.example.org\r\n"
1961 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:231962 };
1963
[email protected]038e9a32008-10-08 22:40:161964 MockRead data_reads1[] = {
1965 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1966 // Give a couple authenticate options (only the middle one is actually
1967 // supported).
[email protected]22927ad2009-09-21 19:56:191968 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161969 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1970 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1971 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1972 // Large content-length -- won't matter, as connection will be reset.
1973 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061974 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161975 };
1976
1977 // After calling trans->RestartWithAuth(), this is the request we should
1978 // be issuing -- the final header line contains the credentials.
1979 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:231980 MockWrite(
1981 "GET / HTTP/1.1\r\n"
1982 "Host: www.example.org\r\n"
1983 "Connection: keep-alive\r\n"
1984 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:161985 };
1986
1987 // Lastly, the server responds with the actual content.
1988 MockRead data_reads2[] = {
1989 MockRead("HTTP/1.0 200 OK\r\n"),
1990 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1991 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061992 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:161993 };
1994
[email protected]31a2bfe2010-02-09 08:03:391995 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1996 data_writes1, arraysize(data_writes1));
1997 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1998 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:071999 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2000 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162001
[email protected]49639fa2011-12-20 23:22:412002 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162003
[email protected]49639fa2011-12-20 23:22:412004 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422005 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162006
2007 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422008 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162009
[email protected]58e32bb2013-01-21 18:23:252010 LoadTimingInfo load_timing_info1;
2011 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2012 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2013
sclittlefb249892015-09-10 21:33:222014 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2015 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2016 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
[email protected]b8015c42013-12-24 15:18:192017 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2018
[email protected]1c773ea12009-04-28 19:58:422019 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502020 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042021 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162022
[email protected]49639fa2011-12-20 23:22:412023 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162024
[email protected]49639fa2011-12-20 23:22:412025 rv = trans->RestartWithAuth(
2026 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422027 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162028
2029 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422030 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162031
[email protected]58e32bb2013-01-21 18:23:252032 LoadTimingInfo load_timing_info2;
2033 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2034 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2035 // The load timing after restart should have a new socket ID, and times after
2036 // those of the first load timing.
2037 EXPECT_LE(load_timing_info1.receive_headers_end,
2038 load_timing_info2.connect_timing.connect_start);
2039 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2040
sclittlefb249892015-09-10 21:33:222041 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2042 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2043 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
[email protected]b8015c42013-12-24 15:18:192044 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2045
[email protected]038e9a32008-10-08 22:40:162046 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502047 ASSERT_TRUE(response != NULL);
[email protected]038e9a32008-10-08 22:40:162048 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2049 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162050}
2051
ttuttled9dbc652015-09-29 20:00:592052// Test the request-challenge-retry sequence for basic auth.
2053// (basic auth is the easiest to mock, because it has no randomness).
2054TEST_P(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
2055 HttpRequestInfo request;
2056 request.method = "GET";
2057 request.url = GURL("http://www.example.org/");
2058 request.load_flags = 0;
2059
2060 TestNetLog log;
2061 MockHostResolver* resolver = new MockHostResolver();
2062 session_deps_.net_log = &log;
2063 session_deps_.host_resolver.reset(resolver);
mmenkee65e7af2015-10-13 17:16:422064 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
ttuttled9dbc652015-09-29 20:00:592065 scoped_ptr<HttpTransaction> trans(
2066 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2067
2068 resolver->rules()->ClearRules();
2069 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2070
2071 MockWrite data_writes1[] = {
2072 MockWrite("GET / HTTP/1.1\r\n"
2073 "Host: www.example.org\r\n"
2074 "Connection: keep-alive\r\n\r\n"),
2075 };
2076
2077 MockRead data_reads1[] = {
2078 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2079 // Give a couple authenticate options (only the middle one is actually
2080 // supported).
2081 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2082 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2083 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2084 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2085 // Large content-length -- won't matter, as connection will be reset.
2086 MockRead("Content-Length: 10000\r\n\r\n"),
2087 MockRead(SYNCHRONOUS, ERR_FAILED),
2088 };
2089
2090 // After calling trans->RestartWithAuth(), this is the request we should
2091 // be issuing -- the final header line contains the credentials.
2092 MockWrite data_writes2[] = {
2093 MockWrite("GET / HTTP/1.1\r\n"
2094 "Host: www.example.org\r\n"
2095 "Connection: keep-alive\r\n"
2096 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2097 };
2098
2099 // Lastly, the server responds with the actual content.
2100 MockRead data_reads2[] = {
2101 MockRead("HTTP/1.0 200 OK\r\n"),
2102 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2103 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2104 };
2105
2106 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2107 data_writes1, arraysize(data_writes1));
2108 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2109 data_writes2, arraysize(data_writes2));
2110 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2111 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2112
2113 TestCompletionCallback callback1;
2114
2115 EXPECT_EQ(OK, callback1.GetResult(trans->Start(&request, callback1.callback(),
2116 BoundNetLog())));
2117
2118 LoadTimingInfo load_timing_info1;
2119 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2120 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2121
2122 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2123 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2124 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
2125 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2126
2127 const HttpResponseInfo* response = trans->GetResponseInfo();
2128 ASSERT_TRUE(response);
2129 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2130
2131 IPEndPoint endpoint;
2132 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2133 ASSERT_FALSE(endpoint.address().empty());
2134 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2135
2136 resolver->rules()->ClearRules();
2137 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2138
2139 TestCompletionCallback callback2;
2140
2141 EXPECT_EQ(OK, callback2.GetResult(trans->RestartWithAuth(
2142 AuthCredentials(kFoo, kBar), callback2.callback())));
2143
2144 LoadTimingInfo load_timing_info2;
2145 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2146 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2147 // The load timing after restart should have a new socket ID, and times after
2148 // those of the first load timing.
2149 EXPECT_LE(load_timing_info1.receive_headers_end,
2150 load_timing_info2.connect_timing.connect_start);
2151 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2152
2153 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2154 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2155 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
2156 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2157
2158 response = trans->GetResponseInfo();
2159 ASSERT_TRUE(response);
2160 EXPECT_FALSE(response->auth_challenge.get());
2161 EXPECT_EQ(100, response->headers->GetContentLength());
2162
2163 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2164 ASSERT_FALSE(endpoint.address().empty());
2165 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2166}
2167
[email protected]23e482282013-06-14 16:08:022168TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462169 HttpRequestInfo request;
2170 request.method = "GET";
bncce36dca22015-04-21 22:11:232171 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292172 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]861fcd52009-08-26 02:33:462173
mmenkee65e7af2015-10-13 17:16:422174 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272175 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:412176 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:272177
[email protected]861fcd52009-08-26 02:33:462178 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232179 MockWrite(
2180 "GET / HTTP/1.1\r\n"
2181 "Host: www.example.org\r\n"
2182 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462183 };
2184
2185 MockRead data_reads[] = {
2186 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2187 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2188 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2189 // Large content-length -- won't matter, as connection will be reset.
2190 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062191 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462192 };
2193
[email protected]31a2bfe2010-02-09 08:03:392194 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2195 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:072196 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412197 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462198
[email protected]49639fa2011-12-20 23:22:412199 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]861fcd52009-08-26 02:33:462200 EXPECT_EQ(ERR_IO_PENDING, rv);
2201
2202 rv = callback.WaitForResult();
2203 EXPECT_EQ(0, rv);
2204
sclittlefb249892015-09-10 21:33:222205 int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes));
2206 EXPECT_EQ(writes_size, trans->GetTotalSentBytes());
2207 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
[email protected]b8015c42013-12-24 15:18:192208 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2209
[email protected]861fcd52009-08-26 02:33:462210 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502211 ASSERT_TRUE(response != NULL);
[email protected]861fcd52009-08-26 02:33:462212 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2213}
2214
[email protected]2d2697f92009-02-18 21:00:322215// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2216// connection.
[email protected]23e482282013-06-14 16:08:022217TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]1c773ea12009-04-28 19:58:422218 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322219 request.method = "GET";
bncce36dca22015-04-21 22:11:232220 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322221 request.load_flags = 0;
2222
vishal.b62985ca92015-04-17 08:45:512223 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072224 session_deps_.net_log = &log;
mmenkee65e7af2015-10-13 17:16:422225 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272226
[email protected]2d2697f92009-02-18 21:00:322227 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232228 MockWrite(
2229 "GET / HTTP/1.1\r\n"
2230 "Host: www.example.org\r\n"
2231 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322232
bncce36dca22015-04-21 22:11:232233 // After calling trans->RestartWithAuth(), this is the request we should
2234 // be issuing -- the final header line contains the credentials.
2235 MockWrite(
2236 "GET / HTTP/1.1\r\n"
2237 "Host: www.example.org\r\n"
2238 "Connection: keep-alive\r\n"
2239 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322240 };
2241
2242 MockRead data_reads1[] = {
2243 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2244 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2245 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2246 MockRead("Content-Length: 14\r\n\r\n"),
2247 MockRead("Unauthorized\r\n"),
2248
2249 // Lastly, the server responds with the actual content.
2250 MockRead("HTTP/1.1 200 OK\r\n"),
2251 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502252 MockRead("Content-Length: 5\r\n\r\n"),
2253 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:322254 };
2255
[email protected]2d0a4f92011-05-05 16:38:462256 // If there is a regression where we disconnect a Keep-Alive
2257 // connection during an auth roundtrip, we'll end up reading this.
2258 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062259 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462260 };
2261
[email protected]31a2bfe2010-02-09 08:03:392262 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2263 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462264 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2265 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072266 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2267 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322268
[email protected]49639fa2011-12-20 23:22:412269 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322270
[email protected]262eec82013-03-19 21:01:362271 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502272 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412273 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422274 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322275
2276 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422277 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322278
[email protected]58e32bb2013-01-21 18:23:252279 LoadTimingInfo load_timing_info1;
2280 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2281 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2282
[email protected]1c773ea12009-04-28 19:58:422283 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502284 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042285 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322286
[email protected]49639fa2011-12-20 23:22:412287 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322288
[email protected]49639fa2011-12-20 23:22:412289 rv = trans->RestartWithAuth(
2290 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422291 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322292
2293 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422294 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322295
[email protected]58e32bb2013-01-21 18:23:252296 LoadTimingInfo load_timing_info2;
2297 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2298 TestLoadTimingReused(load_timing_info2);
2299 // The load timing after restart should have the same socket ID, and times
2300 // those of the first load timing.
2301 EXPECT_LE(load_timing_info1.receive_headers_end,
2302 load_timing_info2.send_start);
2303 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2304
[email protected]2d2697f92009-02-18 21:00:322305 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502306 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322307 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502308 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]b8015c42013-12-24 15:18:192309
2310 std::string response_data;
2311 rv = ReadTransaction(trans.get(), &response_data);
2312 EXPECT_EQ(OK, rv);
sclittlefb249892015-09-10 21:33:222313
2314 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2315 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2316 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
[email protected]b8015c42013-12-24 15:18:192317 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
[email protected]2d2697f92009-02-18 21:00:322318}
2319
2320// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2321// connection and with no response body to drain.
[email protected]23e482282013-06-14 16:08:022322TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:422323 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322324 request.method = "GET";
bncce36dca22015-04-21 22:11:232325 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322326 request.load_flags = 0;
2327
mmenkee65e7af2015-10-13 17:16:422328 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272329
[email protected]2d2697f92009-02-18 21:00:322330 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232331 MockWrite(
2332 "GET / HTTP/1.1\r\n"
2333 "Host: www.example.org\r\n"
2334 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322335
bncce36dca22015-04-21 22:11:232336 // After calling trans->RestartWithAuth(), this is the request we should
2337 // be issuing -- the final header line contains the credentials.
2338 MockWrite(
2339 "GET / HTTP/1.1\r\n"
2340 "Host: www.example.org\r\n"
2341 "Connection: keep-alive\r\n"
2342 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322343 };
2344
[email protected]2d2697f92009-02-18 21:00:322345 MockRead data_reads1[] = {
2346 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2347 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:312348 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:322349
2350 // Lastly, the server responds with the actual content.
2351 MockRead("HTTP/1.1 200 OK\r\n"),
2352 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502353 MockRead("Content-Length: 5\r\n\r\n"),
2354 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322355 };
2356
[email protected]2d0a4f92011-05-05 16:38:462357 // An incorrect reconnect would cause this to be read.
2358 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062359 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462360 };
2361
[email protected]31a2bfe2010-02-09 08:03:392362 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2363 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462364 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2365 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072366 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2367 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322368
[email protected]49639fa2011-12-20 23:22:412369 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322370
[email protected]262eec82013-03-19 21:01:362371 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502372 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412373 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422374 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322375
2376 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422377 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322378
[email protected]1c773ea12009-04-28 19:58:422379 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502380 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042381 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322382
[email protected]49639fa2011-12-20 23:22:412383 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322384
[email protected]49639fa2011-12-20 23:22:412385 rv = trans->RestartWithAuth(
2386 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422387 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322388
2389 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422390 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322391
2392 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502393 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322394 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502395 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322396}
2397
2398// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2399// connection and with a large response body to drain.
[email protected]23e482282013-06-14 16:08:022400TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:422401 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322402 request.method = "GET";
bncce36dca22015-04-21 22:11:232403 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322404 request.load_flags = 0;
2405
mmenkee65e7af2015-10-13 17:16:422406 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272407
[email protected]2d2697f92009-02-18 21:00:322408 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232409 MockWrite(
2410 "GET / HTTP/1.1\r\n"
2411 "Host: www.example.org\r\n"
2412 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322413
bncce36dca22015-04-21 22:11:232414 // After calling trans->RestartWithAuth(), this is the request we should
2415 // be issuing -- the final header line contains the credentials.
2416 MockWrite(
2417 "GET / HTTP/1.1\r\n"
2418 "Host: www.example.org\r\n"
2419 "Connection: keep-alive\r\n"
2420 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322421 };
2422
2423 // Respond with 5 kb of response body.
2424 std::string large_body_string("Unauthorized");
2425 large_body_string.append(5 * 1024, ' ');
2426 large_body_string.append("\r\n");
2427
2428 MockRead data_reads1[] = {
2429 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2430 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2431 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2432 // 5134 = 12 + 5 * 1024 + 2
2433 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062434 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:322435
2436 // Lastly, the server responds with the actual content.
2437 MockRead("HTTP/1.1 200 OK\r\n"),
2438 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502439 MockRead("Content-Length: 5\r\n\r\n"),
2440 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322441 };
2442
[email protected]2d0a4f92011-05-05 16:38:462443 // An incorrect reconnect would cause this to be read.
2444 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062445 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462446 };
2447
[email protected]31a2bfe2010-02-09 08:03:392448 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2449 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462450 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2451 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072452 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2453 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322454
[email protected]49639fa2011-12-20 23:22:412455 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322456
[email protected]262eec82013-03-19 21:01:362457 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502458 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412459 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422460 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322461
2462 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422463 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322464
[email protected]1c773ea12009-04-28 19:58:422465 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502466 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042467 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322468
[email protected]49639fa2011-12-20 23:22:412469 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322470
[email protected]49639fa2011-12-20 23:22:412471 rv = trans->RestartWithAuth(
2472 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422473 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322474
2475 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422476 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322477
2478 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502479 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322480 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502481 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322482}
2483
2484// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:312485// connection, but the server gets impatient and closes the connection.
[email protected]23e482282013-06-14 16:08:022486TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:312487 HttpRequestInfo request;
2488 request.method = "GET";
bncce36dca22015-04-21 22:11:232489 request.url = GURL("http://www.example.org/");
[email protected]11203f012009-11-12 23:02:312490 request.load_flags = 0;
2491
mmenkee65e7af2015-10-13 17:16:422492 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272493
[email protected]11203f012009-11-12 23:02:312494 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232495 MockWrite(
2496 "GET / HTTP/1.1\r\n"
2497 "Host: www.example.org\r\n"
2498 "Connection: keep-alive\r\n\r\n"),
2499 // This simulates the seemingly successful write to a closed connection
2500 // if the bug is not fixed.
2501 MockWrite(
2502 "GET / HTTP/1.1\r\n"
2503 "Host: www.example.org\r\n"
2504 "Connection: keep-alive\r\n"
2505 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312506 };
2507
2508 MockRead data_reads1[] = {
2509 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2510 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2511 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2512 MockRead("Content-Length: 14\r\n\r\n"),
2513 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:062514 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:312515 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:062516 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:312517 };
2518
2519 // After calling trans->RestartWithAuth(), this is the request we should
2520 // be issuing -- the final header line contains the credentials.
2521 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232522 MockWrite(
2523 "GET / HTTP/1.1\r\n"
2524 "Host: www.example.org\r\n"
2525 "Connection: keep-alive\r\n"
2526 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312527 };
2528
2529 // Lastly, the server responds with the actual content.
2530 MockRead data_reads2[] = {
2531 MockRead("HTTP/1.1 200 OK\r\n"),
2532 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502533 MockRead("Content-Length: 5\r\n\r\n"),
2534 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:312535 };
2536
[email protected]31a2bfe2010-02-09 08:03:392537 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2538 data_writes1, arraysize(data_writes1));
2539 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2540 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:072541 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2542 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:312543
[email protected]49639fa2011-12-20 23:22:412544 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:312545
[email protected]262eec82013-03-19 21:01:362546 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502547 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412548 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]11203f012009-11-12 23:02:312549 EXPECT_EQ(ERR_IO_PENDING, rv);
2550
2551 rv = callback1.WaitForResult();
2552 EXPECT_EQ(OK, rv);
2553
2554 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502555 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042556 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]11203f012009-11-12 23:02:312557
[email protected]49639fa2011-12-20 23:22:412558 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:312559
[email protected]49639fa2011-12-20 23:22:412560 rv = trans->RestartWithAuth(
2561 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]11203f012009-11-12 23:02:312562 EXPECT_EQ(ERR_IO_PENDING, rv);
2563
2564 rv = callback2.WaitForResult();
2565 EXPECT_EQ(OK, rv);
2566
2567 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502568 ASSERT_TRUE(response != NULL);
[email protected]11203f012009-11-12 23:02:312569 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502570 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:312571}
2572
[email protected]394816e92010-08-03 07:38:592573// Test the request-challenge-retry sequence for basic auth, over a connection
2574// that requires a restart when setting up an SSL tunnel.
ttuttle34f63b52015-03-05 04:33:012575TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
2576 HttpRequestInfo request;
2577 request.method = "GET";
bncce36dca22015-04-21 22:11:232578 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:012579 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292580 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:012581
2582 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032583 session_deps_.proxy_service =
2584 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512585 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:012586 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:422587 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:012588
2589 // Since we have proxy, should try to establish tunnel.
2590 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542591 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172592 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542593 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:012594 };
2595
mmenkee71e15332015-10-07 16:39:542596 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:012597 // connection.
2598 MockRead data_reads1[] = {
2599 // No credentials.
2600 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2601 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:542602 };
ttuttle34f63b52015-03-05 04:33:012603
mmenkee71e15332015-10-07 16:39:542604 // Since the first connection couldn't be reused, need to establish another
2605 // once given credentials.
2606 MockWrite data_writes2[] = {
2607 // After calling trans->RestartWithAuth(), this is the request we should
2608 // be issuing -- the final header line contains the credentials.
2609 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"
2612 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2613
2614 MockWrite("GET / HTTP/1.1\r\n"
2615 "Host: www.example.org\r\n"
2616 "Connection: keep-alive\r\n\r\n"),
2617 };
2618
2619 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:012620 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2621
2622 MockRead("HTTP/1.1 200 OK\r\n"),
2623 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2624 MockRead("Content-Length: 5\r\n\r\n"),
2625 MockRead(SYNCHRONOUS, "hello"),
2626 };
2627
2628 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2629 data_writes1, arraysize(data_writes1));
2630 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542631 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2632 data_writes2, arraysize(data_writes2));
2633 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:012634 SSLSocketDataProvider ssl(ASYNC, OK);
2635 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2636
2637 TestCompletionCallback callback1;
2638
2639 scoped_ptr<HttpTransaction> trans(
2640 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2641
2642 int rv = trans->Start(&request, callback1.callback(), log.bound());
2643 EXPECT_EQ(ERR_IO_PENDING, rv);
2644
2645 rv = callback1.WaitForResult();
2646 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462647 TestNetLogEntry::List entries;
ttuttle34f63b52015-03-05 04:33:012648 log.GetEntries(&entries);
2649 size_t pos = ExpectLogContainsSomewhere(
2650 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2651 NetLog::PHASE_NONE);
2652 ExpectLogContainsSomewhere(
2653 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2654 NetLog::PHASE_NONE);
2655
2656 const HttpResponseInfo* response = trans->GetResponseInfo();
2657 ASSERT_TRUE(response != NULL);
2658 EXPECT_FALSE(response->headers->IsKeepAlive());
2659 ASSERT_FALSE(response->headers.get() == NULL);
2660 EXPECT_EQ(407, response->headers->response_code());
2661 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2662 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2663
2664 LoadTimingInfo load_timing_info;
2665 // CONNECT requests and responses are handled at the connect job level, so
2666 // the transaction does not yet have a connection.
2667 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2668
2669 TestCompletionCallback callback2;
2670
2671 rv =
2672 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
2673 EXPECT_EQ(ERR_IO_PENDING, rv);
2674
2675 rv = callback2.WaitForResult();
2676 EXPECT_EQ(OK, rv);
2677
2678 response = trans->GetResponseInfo();
2679 ASSERT_TRUE(response != NULL);
2680
2681 EXPECT_TRUE(response->headers->IsKeepAlive());
2682 EXPECT_EQ(200, response->headers->response_code());
2683 EXPECT_EQ(5, response->headers->GetContentLength());
2684 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2685
2686 // The password prompt info should not be set.
2687 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2688
2689 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2690 TestLoadTimingNotReusedWithPac(load_timing_info,
2691 CONNECT_TIMING_HAS_SSL_TIMES);
2692
2693 trans.reset();
2694 session->CloseAllConnections();
2695}
2696
2697// Test the request-challenge-retry sequence for basic auth, over a connection
2698// that requires a restart when setting up an SSL tunnel.
2699TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:592700 HttpRequestInfo request;
2701 request.method = "GET";
bncce36dca22015-04-21 22:11:232702 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:592703 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292704 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]394816e92010-08-03 07:38:592705
[email protected]cb9bf6ca2011-01-28 13:15:272706 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032707 session_deps_.proxy_service =
2708 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512709 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072710 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:422711 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272712
[email protected]394816e92010-08-03 07:38:592713 // Since we have proxy, should try to establish tunnel.
2714 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542715 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172716 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542717 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:112718 };
2719
mmenkee71e15332015-10-07 16:39:542720 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:082721 // connection.
2722 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:542723 // No credentials.
2724 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2725 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2726 MockRead("Proxy-Connection: close\r\n\r\n"),
2727 };
mmenkee0b5c882015-08-26 20:29:112728
mmenkee71e15332015-10-07 16:39:542729 MockWrite data_writes2[] = {
2730 // After calling trans->RestartWithAuth(), this is the request we should
2731 // be issuing -- the final header line contains the credentials.
2732 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172733 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542734 "Proxy-Connection: keep-alive\r\n"
2735 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:082736
mmenkee71e15332015-10-07 16:39:542737 MockWrite("GET / HTTP/1.1\r\n"
2738 "Host: www.example.org\r\n"
2739 "Connection: keep-alive\r\n\r\n"),
2740 };
2741
2742 MockRead data_reads2[] = {
2743 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2744
2745 MockRead("HTTP/1.1 200 OK\r\n"),
2746 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2747 MockRead("Content-Length: 5\r\n\r\n"),
2748 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:592749 };
2750
2751 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2752 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:072753 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542754 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2755 data_writes2, arraysize(data_writes2));
2756 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:062757 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:072758 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:592759
[email protected]49639fa2011-12-20 23:22:412760 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:592761
[email protected]262eec82013-03-19 21:01:362762 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502763 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:502764
[email protected]49639fa2011-12-20 23:22:412765 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]394816e92010-08-03 07:38:592766 EXPECT_EQ(ERR_IO_PENDING, rv);
2767
2768 rv = callback1.WaitForResult();
2769 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462770 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:402771 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:592772 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402773 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:592774 NetLog::PHASE_NONE);
2775 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402776 entries, pos,
[email protected]394816e92010-08-03 07:38:592777 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2778 NetLog::PHASE_NONE);
2779
2780 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502781 ASSERT_TRUE(response != NULL);
ttuttle34f63b52015-03-05 04:33:012782 EXPECT_FALSE(response->headers->IsKeepAlive());
[email protected]90499482013-06-01 00:39:502783 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]394816e92010-08-03 07:38:592784 EXPECT_EQ(407, response->headers->response_code());
2785 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042786 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]394816e92010-08-03 07:38:592787
[email protected]029c83b62013-01-24 05:28:202788 LoadTimingInfo load_timing_info;
2789 // CONNECT requests and responses are handled at the connect job level, so
2790 // the transaction does not yet have a connection.
2791 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2792
[email protected]49639fa2011-12-20 23:22:412793 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:592794
[email protected]49639fa2011-12-20 23:22:412795 rv = trans->RestartWithAuth(
2796 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]394816e92010-08-03 07:38:592797 EXPECT_EQ(ERR_IO_PENDING, rv);
2798
2799 rv = callback2.WaitForResult();
2800 EXPECT_EQ(OK, rv);
2801
2802 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502803 ASSERT_TRUE(response != NULL);
[email protected]394816e92010-08-03 07:38:592804
2805 EXPECT_TRUE(response->headers->IsKeepAlive());
2806 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:502807 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:592808 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2809
2810 // The password prompt info should not be set.
2811 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502812
[email protected]029c83b62013-01-24 05:28:202813 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2814 TestLoadTimingNotReusedWithPac(load_timing_info,
2815 CONNECT_TIMING_HAS_SSL_TIMES);
2816
[email protected]0b0bf032010-09-21 18:08:502817 trans.reset();
[email protected]102e27c2011-02-23 01:01:312818 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:592819}
2820
[email protected]11203f012009-11-12 23:02:312821// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:012822// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2823TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
2824 HttpRequestInfo request;
2825 request.method = "GET";
bncce36dca22015-04-21 22:11:232826 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:012827 // Ensure that proxy authentication is attempted even
2828 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292829 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:012830
2831 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032832 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:512833 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:012834 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:422835 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:012836
2837 scoped_ptr<HttpTransaction> trans(
2838 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2839
2840 // Since we have proxy, should try to establish tunnel.
2841 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:172842 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2843 "Host: www.example.org:443\r\n"
2844 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:012845
2846 // After calling trans->RestartWithAuth(), this is the request we should
2847 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:172848 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2849 "Host: www.example.org:443\r\n"
2850 "Proxy-Connection: keep-alive\r\n"
2851 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:012852 };
2853
2854 // The proxy responds to the connect with a 407, using a persistent
2855 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2856 MockRead data_reads1[] = {
2857 // No credentials.
2858 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2859 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2860 MockRead("Proxy-Connection: keep-alive\r\n"),
2861 MockRead("Content-Length: 10\r\n\r\n"),
2862 MockRead("0123456789"),
2863
2864 // Wrong credentials (wrong password).
2865 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2866 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2867 MockRead("Proxy-Connection: keep-alive\r\n"),
2868 MockRead("Content-Length: 10\r\n\r\n"),
2869 // No response body because the test stops reading here.
2870 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2871 };
2872
2873 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2874 data_writes1, arraysize(data_writes1));
2875 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2876
2877 TestCompletionCallback callback1;
2878
2879 int rv = trans->Start(&request, callback1.callback(), log.bound());
2880 EXPECT_EQ(ERR_IO_PENDING, rv);
2881
2882 rv = callback1.WaitForResult();
2883 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462884 TestNetLogEntry::List entries;
ttuttle34f63b52015-03-05 04:33:012885 log.GetEntries(&entries);
2886 size_t pos = ExpectLogContainsSomewhere(
2887 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2888 NetLog::PHASE_NONE);
2889 ExpectLogContainsSomewhere(
2890 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2891 NetLog::PHASE_NONE);
2892
2893 const HttpResponseInfo* response = trans->GetResponseInfo();
2894 ASSERT_TRUE(response);
2895 ASSERT_TRUE(response->headers);
2896 EXPECT_TRUE(response->headers->IsKeepAlive());
2897 EXPECT_EQ(407, response->headers->response_code());
2898 EXPECT_EQ(10, response->headers->GetContentLength());
2899 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2900 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2901
2902 TestCompletionCallback callback2;
2903
2904 // Wrong password (should be "bar").
2905 rv =
2906 trans->RestartWithAuth(AuthCredentials(kFoo, kBaz), callback2.callback());
2907 EXPECT_EQ(ERR_IO_PENDING, rv);
2908
2909 rv = callback2.WaitForResult();
2910 EXPECT_EQ(OK, rv);
2911
2912 response = trans->GetResponseInfo();
2913 ASSERT_TRUE(response);
2914 ASSERT_TRUE(response->headers);
2915 EXPECT_TRUE(response->headers->IsKeepAlive());
2916 EXPECT_EQ(407, response->headers->response_code());
2917 EXPECT_EQ(10, response->headers->GetContentLength());
2918 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2919 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2920
2921 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2922 // out of scope.
2923 session->CloseAllConnections();
2924}
2925
2926// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2927// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2928TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
[email protected]cb9bf6ca2011-01-28 13:15:272929 HttpRequestInfo request;
2930 request.method = "GET";
bncce36dca22015-04-21 22:11:232931 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:272932 // Ensure that proxy authentication is attempted even
2933 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292934 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]cb9bf6ca2011-01-28 13:15:272935
[email protected]2d2697f92009-02-18 21:00:322936 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032937 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:512938 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072939 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:422940 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:322941
[email protected]262eec82013-03-19 21:01:362942 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502943 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d2697f92009-02-18 21:00:322944
[email protected]2d2697f92009-02-18 21:00:322945 // Since we have proxy, should try to establish tunnel.
2946 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:172947 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2948 "Host: www.example.org:443\r\n"
2949 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322950
bncce36dca22015-04-21 22:11:232951 // After calling trans->RestartWithAuth(), this is the request we should
2952 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:172953 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2954 "Host: www.example.org:443\r\n"
2955 "Proxy-Connection: keep-alive\r\n"
2956 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322957 };
2958
2959 // The proxy responds to the connect with a 407, using a persistent
2960 // connection.
2961 MockRead data_reads1[] = {
2962 // No credentials.
2963 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2964 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2965 MockRead("Content-Length: 10\r\n\r\n"),
2966 MockRead("0123456789"),
2967
2968 // Wrong credentials (wrong password).
2969 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2970 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2971 MockRead("Content-Length: 10\r\n\r\n"),
2972 // No response body because the test stops reading here.
[email protected]8ddf8322012-02-23 18:08:062973 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:322974 };
2975
[email protected]31a2bfe2010-02-09 08:03:392976 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2977 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:072978 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:322979
[email protected]49639fa2011-12-20 23:22:412980 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322981
[email protected]49639fa2011-12-20 23:22:412982 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]1c773ea12009-04-28 19:58:422983 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322984
2985 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422986 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462987 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:402988 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:392989 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402990 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:392991 NetLog::PHASE_NONE);
2992 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402993 entries, pos,
[email protected]dbb83db2010-05-11 18:13:392994 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2995 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:322996
[email protected]1c773ea12009-04-28 19:58:422997 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:242998 ASSERT_TRUE(response);
2999 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323000 EXPECT_TRUE(response->headers->IsKeepAlive());
3001 EXPECT_EQ(407, response->headers->response_code());
ttuttle34f63b52015-03-05 04:33:013002 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423003 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:043004 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:323005
[email protected]49639fa2011-12-20 23:22:413006 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323007
3008 // Wrong password (should be "bar").
[email protected]49639fa2011-12-20 23:22:413009 rv = trans->RestartWithAuth(
3010 AuthCredentials(kFoo, kBaz), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:423011 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:323012
3013 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423014 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:323015
3016 response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243017 ASSERT_TRUE(response);
3018 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323019 EXPECT_TRUE(response->headers->IsKeepAlive());
3020 EXPECT_EQ(407, response->headers->response_code());
ttuttle34f63b52015-03-05 04:33:013021 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423022 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:043023 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]e772db3f2010-07-12 18:11:133024
[email protected]e60e47a2010-07-14 03:37:183025 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3026 // out of scope.
[email protected]102e27c2011-02-23 01:01:313027 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323028}
3029
mmenkee71e15332015-10-07 16:39:543030// Test the case a proxy closes a socket while the challenge body is being
3031// drained.
3032TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
3033 HttpRequestInfo request;
3034 request.method = "GET";
3035 request.url = GURL("https://www.example.org/");
3036 // Ensure that proxy authentication is attempted even
3037 // when the no authentication data flag is set.
3038 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
3039
3040 // Configure against proxy server "myproxy:70".
3041 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:423042 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543043
3044 scoped_ptr<HttpTransaction> trans(
3045 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3046
3047 // Since we have proxy, should try to establish tunnel.
3048 MockWrite data_writes1[] = {
3049 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173050 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543051 "Proxy-Connection: keep-alive\r\n\r\n"),
3052 };
3053
3054 // The proxy responds to the connect with a 407, using a persistent
3055 // connection.
3056 MockRead data_reads1[] = {
3057 // No credentials.
3058 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3059 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3060 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3061 // Server hands up in the middle of the body.
3062 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3063 };
3064
3065 MockWrite data_writes2[] = {
3066 // After calling trans->RestartWithAuth(), this is the request we should
3067 // be issuing -- the final header line contains the credentials.
3068 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173069 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543070 "Proxy-Connection: keep-alive\r\n"
3071 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3072
3073 MockWrite("GET / HTTP/1.1\r\n"
3074 "Host: www.example.org\r\n"
3075 "Connection: keep-alive\r\n\r\n"),
3076 };
3077
3078 MockRead data_reads2[] = {
3079 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3080
3081 MockRead("HTTP/1.1 200 OK\r\n"),
3082 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3083 MockRead("Content-Length: 5\r\n\r\n"),
3084 MockRead(SYNCHRONOUS, "hello"),
3085 };
3086
3087 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3088 data_writes1, arraysize(data_writes1));
3089 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3090 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3091 data_writes2, arraysize(data_writes2));
3092 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3093 SSLSocketDataProvider ssl(ASYNC, OK);
3094 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3095
3096 TestCompletionCallback callback;
3097
3098 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3099 EXPECT_EQ(OK, callback.GetResult(rv));
3100
3101 const HttpResponseInfo* response = trans->GetResponseInfo();
3102 ASSERT_TRUE(response);
3103 ASSERT_TRUE(response->headers);
3104 EXPECT_TRUE(response->headers->IsKeepAlive());
3105 EXPECT_EQ(407, response->headers->response_code());
3106 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3107
3108 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
3109 EXPECT_EQ(OK, callback.GetResult(rv));
3110
3111 response = trans->GetResponseInfo();
3112 ASSERT_TRUE(response);
3113 ASSERT_TRUE(response->headers);
3114 EXPECT_TRUE(response->headers->IsKeepAlive());
3115 EXPECT_EQ(200, response->headers->response_code());
3116 std::string body;
3117 EXPECT_EQ(OK, ReadTransaction(trans.get(), &body));
3118 EXPECT_EQ("hello", body);
3119}
3120
[email protected]a8e9b162009-03-12 00:06:443121// Test that we don't read the response body when we fail to establish a tunnel,
3122// even if the user cancels the proxy's auth attempt.
[email protected]23e482282013-06-14 16:08:023123TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273124 HttpRequestInfo request;
3125 request.method = "GET";
bncce36dca22015-04-21 22:11:233126 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273127 request.load_flags = 0;
3128
[email protected]a8e9b162009-03-12 00:06:443129 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033130 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]a8e9b162009-03-12 00:06:443131
mmenkee65e7af2015-10-13 17:16:423132 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443133
[email protected]262eec82013-03-19 21:01:363134 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503135 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]a8e9b162009-03-12 00:06:443136
[email protected]a8e9b162009-03-12 00:06:443137 // Since we have proxy, should try to establish tunnel.
3138 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173139 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3140 "Host: www.example.org:443\r\n"
3141 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443142 };
3143
3144 // The proxy responds to the connect with a 407.
3145 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243146 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3147 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3148 MockRead("Content-Length: 10\r\n\r\n"),
3149 MockRead("0123456789"), // Should not be reached.
3150 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443151 };
3152
[email protected]31a2bfe2010-02-09 08:03:393153 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3154 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:073155 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443156
[email protected]49639fa2011-12-20 23:22:413157 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443158
[email protected]49639fa2011-12-20 23:22:413159 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423160 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:443161
3162 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423163 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:443164
[email protected]1c773ea12009-04-28 19:58:423165 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243166 ASSERT_TRUE(response);
3167 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:443168 EXPECT_TRUE(response->headers->IsKeepAlive());
3169 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423170 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:443171
3172 std::string response_data;
3173 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423174 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:183175
3176 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:313177 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:443178}
3179
ttuttle7933c112015-01-06 00:55:243180// Test that we don't pass extraneous headers from the proxy's response to the
3181// caller when the proxy responds to CONNECT with 407.
3182TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
3183 HttpRequestInfo request;
3184 request.method = "GET";
bncce36dca22015-04-21 22:11:233185 request.url = GURL("https://www.example.org/");
ttuttle7933c112015-01-06 00:55:243186 request.load_flags = 0;
3187
3188 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033189 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
ttuttle7933c112015-01-06 00:55:243190
mmenkee65e7af2015-10-13 17:16:423191 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:243192
3193 scoped_ptr<HttpTransaction> trans(
3194 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3195
3196 // Since we have proxy, should try to establish tunnel.
3197 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173198 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3199 "Host: www.example.org:443\r\n"
3200 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:243201 };
3202
3203 // The proxy responds to the connect with a 407.
3204 MockRead data_reads[] = {
3205 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3206 MockRead("X-Foo: bar\r\n"),
3207 MockRead("Set-Cookie: foo=bar\r\n"),
3208 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3209 MockRead("Content-Length: 10\r\n\r\n"),
3210 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
3211 };
3212
3213 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
3214 arraysize(data_writes));
3215 session_deps_.socket_factory->AddSocketDataProvider(&data);
3216
3217 TestCompletionCallback callback;
3218
3219 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3220 EXPECT_EQ(ERR_IO_PENDING, rv);
3221
3222 rv = callback.WaitForResult();
3223 EXPECT_EQ(OK, rv);
3224
3225 const HttpResponseInfo* response = trans->GetResponseInfo();
3226 ASSERT_TRUE(response);
3227 ASSERT_TRUE(response->headers);
3228 EXPECT_TRUE(response->headers->IsKeepAlive());
3229 EXPECT_EQ(407, response->headers->response_code());
3230 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3231 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
3232 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
3233
3234 std::string response_data;
3235 rv = ReadTransaction(trans.get(), &response_data);
3236 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3237
3238 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3239 session->CloseAllConnections();
3240}
3241
[email protected]8fdbcd22010-05-05 02:54:523242// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
3243// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
[email protected]23e482282013-06-14 16:08:023244TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:523245 HttpRequestInfo request;
3246 request.method = "GET";
bncce36dca22015-04-21 22:11:233247 request.url = GURL("http://www.example.org/");
[email protected]8fdbcd22010-05-05 02:54:523248 request.load_flags = 0;
3249
[email protected]cb9bf6ca2011-01-28 13:15:273250 // We are using a DIRECT connection (i.e. no proxy) for this session.
mmenkee65e7af2015-10-13 17:16:423251 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273252 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:413253 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:273254
[email protected]8fdbcd22010-05-05 02:54:523255 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233256 MockWrite(
3257 "GET / HTTP/1.1\r\n"
3258 "Host: www.example.org\r\n"
3259 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:523260 };
3261
3262 MockRead data_reads1[] = {
3263 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
3264 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3265 // Large content-length -- won't matter, as connection will be reset.
3266 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063267 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:523268 };
3269
3270 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3271 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073272 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:523273
[email protected]49639fa2011-12-20 23:22:413274 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:523275
[email protected]49639fa2011-12-20 23:22:413276 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]8fdbcd22010-05-05 02:54:523277 EXPECT_EQ(ERR_IO_PENDING, rv);
3278
3279 rv = callback.WaitForResult();
3280 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3281}
3282
[email protected]7a67a8152010-11-05 18:31:103283// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3284// through a non-authenticating proxy. The request should fail with
3285// ERR_UNEXPECTED_PROXY_AUTH.
3286// Note that it is impossible to detect if an HTTP server returns a 407 through
3287// a non-authenticating proxy - there is nothing to indicate whether the
3288// response came from the proxy or the server, so it is treated as if the proxy
3289// issued the challenge.
[email protected]23e482282013-06-14 16:08:023290TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:233291 HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:273292 HttpRequestInfo request;
3293 request.method = "GET";
bncce36dca22015-04-21 22:11:233294 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273295
rdsmith82957ad2015-09-16 19:42:033296 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:513297 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073298 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423299 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:103300
[email protected]7a67a8152010-11-05 18:31:103301 // Since we have proxy, should try to establish tunnel.
3302 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:173303 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3304 "Host: www.example.org:443\r\n"
3305 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103306
rsleevidb16bb02015-11-12 23:47:173307 MockWrite("GET / HTTP/1.1\r\n"
3308 "Host: www.example.org\r\n"
3309 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103310 };
3311
3312 MockRead data_reads1[] = {
3313 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3314
3315 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3316 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3317 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:063318 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:103319 };
3320
3321 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3322 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073323 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:063324 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073325 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:103326
[email protected]49639fa2011-12-20 23:22:413327 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:103328
[email protected]262eec82013-03-19 21:01:363329 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503330 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a67a8152010-11-05 18:31:103331
[email protected]49639fa2011-12-20 23:22:413332 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7a67a8152010-11-05 18:31:103333 EXPECT_EQ(ERR_IO_PENDING, rv);
3334
3335 rv = callback1.WaitForResult();
3336 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
mmenke43758e62015-05-04 21:09:463337 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403338 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:103339 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403340 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:103341 NetLog::PHASE_NONE);
3342 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403343 entries, pos,
[email protected]7a67a8152010-11-05 18:31:103344 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3345 NetLog::PHASE_NONE);
3346}
[email protected]2df19bb2010-08-25 20:13:463347
mmenke2a1781d2015-10-07 19:25:333348// Test a proxy auth scheme that allows default credentials and a proxy server
3349// that uses non-persistent connections.
3350TEST_P(HttpNetworkTransactionTest,
3351 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
3352 HttpRequestInfo request;
3353 request.method = "GET";
3354 request.url = GURL("https://www.example.org/");
3355
3356 // Configure against proxy server "myproxy:70".
3357 session_deps_.proxy_service =
3358 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3359
3360 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3361 new HttpAuthHandlerMock::Factory());
3362 auth_handler_factory->set_do_init_from_challenge(true);
3363 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3364 mock_handler->set_allows_default_credentials(true);
3365 auth_handler_factory->AddMockHandler(mock_handler.release(),
3366 HttpAuth::AUTH_PROXY);
3367 session_deps_.http_auth_handler_factory = auth_handler_factory.Pass();
3368
3369 // Add NetLog just so can verify load timing information gets a NetLog ID.
3370 NetLog net_log;
3371 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423372 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333373
3374 // Since we have proxy, should try to establish tunnel.
3375 MockWrite data_writes1[] = {
3376 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173377 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333378 "Proxy-Connection: keep-alive\r\n\r\n"),
3379 };
3380
3381 // The proxy responds to the connect with a 407, using a non-persistent
3382 // connection.
3383 MockRead data_reads1[] = {
3384 // No credentials.
3385 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3386 MockRead("Proxy-Authenticate: Mock\r\n"),
3387 MockRead("Proxy-Connection: close\r\n\r\n"),
3388 };
3389
3390 // Since the first connection couldn't be reused, need to establish another
3391 // once given credentials.
3392 MockWrite data_writes2[] = {
3393 // After calling trans->RestartWithAuth(), this is the request we should
3394 // be issuing -- the final header line contains the credentials.
3395 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173396 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333397 "Proxy-Connection: keep-alive\r\n"
3398 "Proxy-Authorization: auth_token\r\n\r\n"),
3399
3400 MockWrite("GET / HTTP/1.1\r\n"
3401 "Host: www.example.org\r\n"
3402 "Connection: keep-alive\r\n\r\n"),
3403 };
3404
3405 MockRead data_reads2[] = {
3406 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3407
3408 MockRead("HTTP/1.1 200 OK\r\n"),
3409 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3410 MockRead("Content-Length: 5\r\n\r\n"),
3411 MockRead(SYNCHRONOUS, "hello"),
3412 };
3413
3414 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3415 data_writes1, arraysize(data_writes1));
3416 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3417 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3418 data_writes2, arraysize(data_writes2));
3419 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3420 SSLSocketDataProvider ssl(ASYNC, OK);
3421 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3422
3423 scoped_ptr<HttpTransaction> trans(
3424 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3425
3426 TestCompletionCallback callback;
3427 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3428 EXPECT_EQ(OK, callback.GetResult(rv));
3429
3430 const HttpResponseInfo* response = trans->GetResponseInfo();
3431 ASSERT_TRUE(response);
3432 ASSERT_TRUE(response->headers);
3433 EXPECT_FALSE(response->headers->IsKeepAlive());
3434 EXPECT_EQ(407, response->headers->response_code());
3435 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3436 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3437 EXPECT_FALSE(response->auth_challenge.get());
3438
3439 LoadTimingInfo load_timing_info;
3440 // CONNECT requests and responses are handled at the connect job level, so
3441 // the transaction does not yet have a connection.
3442 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3443
3444 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3445 EXPECT_EQ(OK, callback.GetResult(rv));
3446 response = trans->GetResponseInfo();
3447 ASSERT_TRUE(response);
3448 ASSERT_TRUE(response->headers);
3449 EXPECT_TRUE(response->headers->IsKeepAlive());
3450 EXPECT_EQ(200, response->headers->response_code());
3451 EXPECT_EQ(5, response->headers->GetContentLength());
3452 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3453
3454 // The password prompt info should not be set.
3455 EXPECT_FALSE(response->auth_challenge);
3456
3457 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3458 TestLoadTimingNotReusedWithPac(load_timing_info,
3459 CONNECT_TIMING_HAS_SSL_TIMES);
3460
3461 trans.reset();
3462 session->CloseAllConnections();
3463}
3464
3465// Test a proxy auth scheme that allows default credentials and a proxy server
3466// that hangs up when credentials are initially sent.
3467TEST_P(HttpNetworkTransactionTest,
3468 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
3469 HttpRequestInfo request;
3470 request.method = "GET";
3471 request.url = GURL("https://www.example.org/");
3472
3473 // Configure against proxy server "myproxy:70".
3474 session_deps_.proxy_service =
3475 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3476
3477 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3478 new HttpAuthHandlerMock::Factory());
3479 auth_handler_factory->set_do_init_from_challenge(true);
3480 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3481 mock_handler->set_allows_default_credentials(true);
3482 auth_handler_factory->AddMockHandler(mock_handler.release(),
3483 HttpAuth::AUTH_PROXY);
3484 session_deps_.http_auth_handler_factory = auth_handler_factory.Pass();
3485
3486 // Add NetLog just so can verify load timing information gets a NetLog ID.
3487 NetLog net_log;
3488 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423489 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333490
3491 // Should try to establish tunnel.
3492 MockWrite data_writes1[] = {
3493 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173494 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333495 "Proxy-Connection: keep-alive\r\n\r\n"),
3496
3497 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173498 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333499 "Proxy-Connection: keep-alive\r\n"
3500 "Proxy-Authorization: auth_token\r\n\r\n"),
3501 };
3502
3503 // The proxy responds to the connect with a 407, using a non-persistent
3504 // connection.
3505 MockRead data_reads1[] = {
3506 // No credentials.
3507 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3508 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3509 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3510 };
3511
3512 // Since the first connection was closed, need to establish another once given
3513 // credentials.
3514 MockWrite data_writes2[] = {
3515 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173516 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333517 "Proxy-Connection: keep-alive\r\n"
3518 "Proxy-Authorization: auth_token\r\n\r\n"),
3519
3520 MockWrite("GET / HTTP/1.1\r\n"
3521 "Host: www.example.org\r\n"
3522 "Connection: keep-alive\r\n\r\n"),
3523 };
3524
3525 MockRead data_reads2[] = {
3526 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3527
3528 MockRead("HTTP/1.1 200 OK\r\n"),
3529 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3530 MockRead("Content-Length: 5\r\n\r\n"),
3531 MockRead(SYNCHRONOUS, "hello"),
3532 };
3533
3534 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3535 data_writes1, arraysize(data_writes1));
3536 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3537 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3538 data_writes2, arraysize(data_writes2));
3539 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3540 SSLSocketDataProvider ssl(ASYNC, OK);
3541 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3542
3543 scoped_ptr<HttpTransaction> trans(
3544 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3545
3546 TestCompletionCallback callback;
3547 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3548 EXPECT_EQ(OK, callback.GetResult(rv));
3549
3550 const HttpResponseInfo* response = trans->GetResponseInfo();
3551 ASSERT_TRUE(response);
3552 ASSERT_TRUE(response->headers);
3553 EXPECT_TRUE(response->headers->IsKeepAlive());
3554 EXPECT_EQ(407, response->headers->response_code());
3555 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3556 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3557 EXPECT_FALSE(response->auth_challenge);
3558
3559 LoadTimingInfo load_timing_info;
3560 // CONNECT requests and responses are handled at the connect job level, so
3561 // the transaction does not yet have a connection.
3562 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3563
3564 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3565 EXPECT_EQ(OK, callback.GetResult(rv));
3566
3567 response = trans->GetResponseInfo();
3568 ASSERT_TRUE(response);
3569 ASSERT_TRUE(response->headers);
3570 EXPECT_TRUE(response->headers->IsKeepAlive());
3571 EXPECT_EQ(200, response->headers->response_code());
3572 EXPECT_EQ(5, response->headers->GetContentLength());
3573 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3574
3575 // The password prompt info should not be set.
3576 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3577
3578 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3579 TestLoadTimingNotReusedWithPac(load_timing_info,
3580 CONNECT_TIMING_HAS_SSL_TIMES);
3581
3582 trans.reset();
3583 session->CloseAllConnections();
3584}
3585
3586// Test a proxy auth scheme that allows default credentials and a proxy server
3587// that hangs up when credentials are initially sent, and hangs up again when
3588// they are retried.
3589TEST_P(HttpNetworkTransactionTest,
3590 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
3591 HttpRequestInfo request;
3592 request.method = "GET";
3593 request.url = GURL("https://www.example.org/");
3594
3595 // Configure against proxy server "myproxy:70".
3596 session_deps_.proxy_service =
3597 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3598
3599 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3600 new HttpAuthHandlerMock::Factory());
3601 auth_handler_factory->set_do_init_from_challenge(true);
3602 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3603 mock_handler->set_allows_default_credentials(true);
3604 auth_handler_factory->AddMockHandler(mock_handler.release(),
3605 HttpAuth::AUTH_PROXY);
3606 session_deps_.http_auth_handler_factory = auth_handler_factory.Pass();
3607
3608 // Add NetLog just so can verify load timing information gets a NetLog ID.
3609 NetLog net_log;
3610 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423611 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333612
3613 // Should try to establish tunnel.
3614 MockWrite data_writes1[] = {
3615 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173616 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333617 "Proxy-Connection: keep-alive\r\n\r\n"),
3618
3619 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173620 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333621 "Proxy-Connection: keep-alive\r\n"
3622 "Proxy-Authorization: auth_token\r\n\r\n"),
3623 };
3624
3625 // The proxy responds to the connect with a 407, and then hangs up after the
3626 // second request is sent.
3627 MockRead data_reads1[] = {
3628 // No credentials.
3629 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3630 MockRead("Content-Length: 0\r\n"),
3631 MockRead("Proxy-Connection: keep-alive\r\n"),
3632 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3633 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3634 };
3635
3636 // HttpNetworkTransaction sees a reused connection that was closed with
3637 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
3638 // request.
3639 MockWrite data_writes2[] = {
3640 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173641 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333642 "Proxy-Connection: keep-alive\r\n\r\n"),
3643 };
3644
3645 // The proxy, having had more than enough of us, just hangs up.
3646 MockRead data_reads2[] = {
3647 // No credentials.
3648 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3649 };
3650
3651 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3652 data_writes1, arraysize(data_writes1));
3653 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3654 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3655 data_writes2, arraysize(data_writes2));
3656 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3657
3658 scoped_ptr<HttpTransaction> trans(
3659 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3660
3661 TestCompletionCallback callback;
3662 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3663 EXPECT_EQ(OK, callback.GetResult(rv));
3664
3665 const HttpResponseInfo* response = trans->GetResponseInfo();
3666 ASSERT_TRUE(response);
3667 ASSERT_TRUE(response->headers);
3668 EXPECT_TRUE(response->headers->IsKeepAlive());
3669 EXPECT_EQ(407, response->headers->response_code());
3670 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3671 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3672 EXPECT_FALSE(response->auth_challenge);
3673
3674 LoadTimingInfo load_timing_info;
3675 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3676
3677 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3678 EXPECT_EQ(ERR_EMPTY_RESPONSE, callback.GetResult(rv));
3679
3680 trans.reset();
3681 session->CloseAllConnections();
3682}
3683
3684// Test a proxy auth scheme that allows default credentials and a proxy server
3685// that hangs up when credentials are initially sent, and sends a challenge
3686// again they are retried.
3687TEST_P(HttpNetworkTransactionTest,
3688 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
3689 HttpRequestInfo request;
3690 request.method = "GET";
3691 request.url = GURL("https://www.example.org/");
3692
3693 // Configure against proxy server "myproxy:70".
3694 session_deps_.proxy_service =
3695 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3696
3697 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3698 new HttpAuthHandlerMock::Factory());
3699 auth_handler_factory->set_do_init_from_challenge(true);
3700 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3701 mock_handler->set_allows_default_credentials(true);
3702 auth_handler_factory->AddMockHandler(mock_handler.release(),
3703 HttpAuth::AUTH_PROXY);
3704 // Add another handler for the second challenge. It supports default
3705 // credentials, but they shouldn't be used, since they were already tried.
3706 mock_handler.reset(new HttpAuthHandlerMock());
3707 mock_handler->set_allows_default_credentials(true);
3708 auth_handler_factory->AddMockHandler(mock_handler.release(),
3709 HttpAuth::AUTH_PROXY);
3710 session_deps_.http_auth_handler_factory = auth_handler_factory.Pass();
3711
3712 // Add NetLog just so can verify load timing information gets a NetLog ID.
3713 NetLog net_log;
3714 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423715 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333716
3717 // Should try to establish tunnel.
3718 MockWrite data_writes1[] = {
3719 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173720 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333721 "Proxy-Connection: keep-alive\r\n\r\n"),
3722 };
3723
3724 // The proxy responds to the connect with a 407, using a non-persistent
3725 // connection.
3726 MockRead data_reads1[] = {
3727 // No credentials.
3728 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3729 MockRead("Proxy-Authenticate: Mock\r\n"),
3730 MockRead("Proxy-Connection: close\r\n\r\n"),
3731 };
3732
3733 // Since the first connection was closed, need to establish another once given
3734 // credentials.
3735 MockWrite data_writes2[] = {
3736 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173737 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333738 "Proxy-Connection: keep-alive\r\n"
3739 "Proxy-Authorization: auth_token\r\n\r\n"),
3740 };
3741
3742 MockRead data_reads2[] = {
3743 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3744 MockRead("Proxy-Authenticate: Mock\r\n"),
3745 MockRead("Proxy-Connection: close\r\n\r\n"),
3746 };
3747
3748 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3749 data_writes1, arraysize(data_writes1));
3750 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3751 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3752 data_writes2, arraysize(data_writes2));
3753 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3754 SSLSocketDataProvider ssl(ASYNC, OK);
3755 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3756
3757 scoped_ptr<HttpTransaction> trans(
3758 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3759
3760 TestCompletionCallback callback;
3761 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3762 EXPECT_EQ(OK, callback.GetResult(rv));
3763
3764 const HttpResponseInfo* response = trans->GetResponseInfo();
3765 ASSERT_TRUE(response);
3766 ASSERT_TRUE(response->headers);
3767 EXPECT_EQ(407, response->headers->response_code());
3768 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3769 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3770 EXPECT_FALSE(response->auth_challenge);
3771
3772 LoadTimingInfo load_timing_info;
3773 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3774
3775 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3776 EXPECT_EQ(OK, callback.GetResult(rv));
3777 response = trans->GetResponseInfo();
3778 ASSERT_TRUE(response);
3779 ASSERT_TRUE(response->headers);
3780 EXPECT_EQ(407, response->headers->response_code());
3781 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3782 EXPECT_TRUE(response->auth_challenge);
3783
3784 trans.reset();
3785 session->CloseAllConnections();
3786}
3787
[email protected]029c83b62013-01-24 05:28:203788// Test the load timing for HTTPS requests with an HTTP proxy.
[email protected]23e482282013-06-14 16:08:023789TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:203790 HttpRequestInfo request1;
3791 request1.method = "GET";
bncce36dca22015-04-21 22:11:233792 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:203793
3794 HttpRequestInfo request2;
3795 request2.method = "GET";
bncce36dca22015-04-21 22:11:233796 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:203797
3798 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033799 session_deps_.proxy_service = ProxyService::CreateFixed("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:513800 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073801 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423802 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:203803
3804 // Since we have proxy, should try to establish tunnel.
3805 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:173806 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3807 "Host: www.example.org:443\r\n"
3808 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203809
rsleevidb16bb02015-11-12 23:47:173810 MockWrite("GET /1 HTTP/1.1\r\n"
3811 "Host: www.example.org\r\n"
3812 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203813
rsleevidb16bb02015-11-12 23:47:173814 MockWrite("GET /2 HTTP/1.1\r\n"
3815 "Host: www.example.org\r\n"
3816 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203817 };
3818
3819 // The proxy responds to the connect with a 407, using a persistent
3820 // connection.
3821 MockRead data_reads1[] = {
3822 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3823
3824 MockRead("HTTP/1.1 200 OK\r\n"),
3825 MockRead("Content-Length: 1\r\n\r\n"),
3826 MockRead(SYNCHRONOUS, "1"),
3827
3828 MockRead("HTTP/1.1 200 OK\r\n"),
3829 MockRead("Content-Length: 2\r\n\r\n"),
3830 MockRead(SYNCHRONOUS, "22"),
3831 };
3832
3833 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3834 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073835 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:203836 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073837 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:203838
3839 TestCompletionCallback callback1;
[email protected]262eec82013-03-19 21:01:363840 scoped_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:503841 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:203842
3843 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3844 EXPECT_EQ(ERR_IO_PENDING, rv);
3845
3846 rv = callback1.WaitForResult();
3847 EXPECT_EQ(OK, rv);
3848
3849 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3850 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:503851 ASSERT_TRUE(response1->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:203852 EXPECT_EQ(1, response1->headers->GetContentLength());
3853
3854 LoadTimingInfo load_timing_info1;
3855 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3856 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
3857
3858 trans1.reset();
3859
3860 TestCompletionCallback callback2;
[email protected]262eec82013-03-19 21:01:363861 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:503862 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:203863
3864 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3865 EXPECT_EQ(ERR_IO_PENDING, rv);
3866
3867 rv = callback2.WaitForResult();
3868 EXPECT_EQ(OK, rv);
3869
3870 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3871 ASSERT_TRUE(response2 != NULL);
[email protected]90499482013-06-01 00:39:503872 ASSERT_TRUE(response2->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:203873 EXPECT_EQ(2, response2->headers->GetContentLength());
3874
3875 LoadTimingInfo load_timing_info2;
3876 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3877 TestLoadTimingReused(load_timing_info2);
3878
3879 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3880
3881 trans2.reset();
3882 session->CloseAllConnections();
3883}
3884
3885// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
[email protected]23e482282013-06-14 16:08:023886TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:203887 HttpRequestInfo request1;
3888 request1.method = "GET";
bncce36dca22015-04-21 22:11:233889 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:203890
3891 HttpRequestInfo request2;
3892 request2.method = "GET";
bncce36dca22015-04-21 22:11:233893 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:203894
3895 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033896 session_deps_.proxy_service =
3897 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:513898 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073899 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423900 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:203901
3902 // Since we have proxy, should try to establish tunnel.
3903 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:173904 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3905 "Host: www.example.org:443\r\n"
3906 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203907
rsleevidb16bb02015-11-12 23:47:173908 MockWrite("GET /1 HTTP/1.1\r\n"
3909 "Host: www.example.org\r\n"
3910 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203911
rsleevidb16bb02015-11-12 23:47:173912 MockWrite("GET /2 HTTP/1.1\r\n"
3913 "Host: www.example.org\r\n"
3914 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203915 };
3916
3917 // The proxy responds to the connect with a 407, using a persistent
3918 // connection.
3919 MockRead data_reads1[] = {
3920 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3921
3922 MockRead("HTTP/1.1 200 OK\r\n"),
3923 MockRead("Content-Length: 1\r\n\r\n"),
3924 MockRead(SYNCHRONOUS, "1"),
3925
3926 MockRead("HTTP/1.1 200 OK\r\n"),
3927 MockRead("Content-Length: 2\r\n\r\n"),
3928 MockRead(SYNCHRONOUS, "22"),
3929 };
3930
3931 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3932 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073933 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:203934 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073935 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:203936
3937 TestCompletionCallback callback1;
[email protected]262eec82013-03-19 21:01:363938 scoped_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:503939 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:203940
3941 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3942 EXPECT_EQ(ERR_IO_PENDING, rv);
3943
3944 rv = callback1.WaitForResult();
3945 EXPECT_EQ(OK, rv);
3946
3947 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3948 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:503949 ASSERT_TRUE(response1->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:203950 EXPECT_EQ(1, response1->headers->GetContentLength());
3951
3952 LoadTimingInfo load_timing_info1;
3953 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3954 TestLoadTimingNotReusedWithPac(load_timing_info1,
3955 CONNECT_TIMING_HAS_SSL_TIMES);
3956
3957 trans1.reset();
3958
3959 TestCompletionCallback callback2;
[email protected]262eec82013-03-19 21:01:363960 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:503961 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:203962
3963 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3964 EXPECT_EQ(ERR_IO_PENDING, rv);
3965
3966 rv = callback2.WaitForResult();
3967 EXPECT_EQ(OK, rv);
3968
3969 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3970 ASSERT_TRUE(response2 != NULL);
[email protected]90499482013-06-01 00:39:503971 ASSERT_TRUE(response2->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:203972 EXPECT_EQ(2, response2->headers->GetContentLength());
3973
3974 LoadTimingInfo load_timing_info2;
3975 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3976 TestLoadTimingReusedWithPac(load_timing_info2);
3977
3978 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3979
3980 trans2.reset();
3981 session->CloseAllConnections();
3982}
3983
[email protected]2df19bb2010-08-25 20:13:463984// Test a simple get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:023985TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:273986 HttpRequestInfo request;
3987 request.method = "GET";
bncce36dca22015-04-21 22:11:233988 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273989
[email protected]2df19bb2010-08-25 20:13:463990 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:033991 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:513992 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073993 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423994 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:463995
[email protected]2df19bb2010-08-25 20:13:463996 // Since we have proxy, should use full url
3997 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233998 MockWrite(
3999 "GET http://www.example.org/ HTTP/1.1\r\n"
4000 "Host: www.example.org\r\n"
4001 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:464002 };
4003
4004 MockRead data_reads1[] = {
4005 MockRead("HTTP/1.1 200 OK\r\n"),
4006 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4007 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064008 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:464009 };
4010
4011 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4012 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074013 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064014 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074015 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:464016
[email protected]49639fa2011-12-20 23:22:414017 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:464018
[email protected]262eec82013-03-19 21:01:364019 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504020 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504021
[email protected]49639fa2011-12-20 23:22:414022 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:464023 EXPECT_EQ(ERR_IO_PENDING, rv);
4024
4025 rv = callback1.WaitForResult();
4026 EXPECT_EQ(OK, rv);
4027
[email protected]58e32bb2013-01-21 18:23:254028 LoadTimingInfo load_timing_info;
4029 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4030 TestLoadTimingNotReused(load_timing_info,
4031 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4032
[email protected]2df19bb2010-08-25 20:13:464033 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504034 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464035
4036 EXPECT_TRUE(response->headers->IsKeepAlive());
4037 EXPECT_EQ(200, response->headers->response_code());
4038 EXPECT_EQ(100, response->headers->GetContentLength());
4039 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4040
4041 // The password prompt info should not be set.
4042 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4043}
4044
[email protected]7642b5ae2010-09-01 20:55:174045// Test a SPDY get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024046TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:274047 HttpRequestInfo request;
4048 request.method = "GET";
bncce36dca22015-04-21 22:11:234049 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274050 request.load_flags = 0;
4051
[email protected]7642b5ae2010-09-01 20:55:174052 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034053 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy: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]7642b5ae2010-09-01 20:55:174057
bncce36dca22015-04-21 22:11:234058 // fetch http://www.example.org/ via SPDY
[email protected]cdf8f7e72013-05-23 10:56:464059 scoped_ptr<SpdyFrame> req(
4060 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rch8e6c6c42015-05-01 14:05:134061 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]7642b5ae2010-09-01 20:55:174062
[email protected]23e482282013-06-14 16:08:024063 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4064 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:174065 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134066 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:174067 };
4068
rch8e6c6c42015-05-01 14:05:134069 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4070 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074071 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:174072
[email protected]8ddf8322012-02-23 18:08:064073 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384074 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074075 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:174076
[email protected]49639fa2011-12-20 23:22:414077 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:174078
[email protected]262eec82013-03-19 21:01:364079 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504080 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504081
[email protected]49639fa2011-12-20 23:22:414082 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7642b5ae2010-09-01 20:55:174083 EXPECT_EQ(ERR_IO_PENDING, rv);
4084
4085 rv = callback1.WaitForResult();
4086 EXPECT_EQ(OK, rv);
4087
[email protected]58e32bb2013-01-21 18:23:254088 LoadTimingInfo load_timing_info;
4089 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4090 TestLoadTimingNotReused(load_timing_info,
4091 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4092
[email protected]7642b5ae2010-09-01 20:55:174093 const HttpResponseInfo* response = trans->GetResponseInfo();
4094 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504095 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024096 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:174097
4098 std::string response_data;
4099 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]448d4ca52012-03-04 04:12:234100 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:174101}
4102
[email protected]1c173852014-06-19 12:51:504103// Verifies that a session which races and wins against the owning transaction
4104// (completing prior to host resolution), doesn't fail the transaction.
4105// Regression test for crbug.com/334413.
4106TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
4107 HttpRequestInfo request;
4108 request.method = "GET";
bncce36dca22015-04-21 22:11:234109 request.url = GURL("http://www.example.org/");
[email protected]1c173852014-06-19 12:51:504110 request.load_flags = 0;
4111
4112 // Configure SPDY proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034113 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514114 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:504115 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424116 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:504117
bncce36dca22015-04-21 22:11:234118 // Fetch http://www.example.org/ through the SPDY proxy.
[email protected]1c173852014-06-19 12:51:504119 scoped_ptr<SpdyFrame> req(
4120 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rch8e6c6c42015-05-01 14:05:134121 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]1c173852014-06-19 12:51:504122
4123 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4124 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
4125 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134126 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:504127 };
4128
rch8e6c6c42015-05-01 14:05:134129 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4130 arraysize(spdy_writes));
[email protected]1c173852014-06-19 12:51:504131 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4132
4133 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384134 ssl.SetNextProto(GetProtocol());
[email protected]1c173852014-06-19 12:51:504135 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4136
4137 TestCompletionCallback callback1;
4138
4139 scoped_ptr<HttpTransaction> trans(
4140 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4141
4142 // Stall the hostname resolution begun by the transaction.
4143 session_deps_.host_resolver->set_synchronous_mode(false);
4144 session_deps_.host_resolver->set_ondemand_mode(true);
4145
4146 int rv = trans->Start(&request, callback1.callback(), log.bound());
4147 EXPECT_EQ(ERR_IO_PENDING, rv);
4148
4149 // Race a session to the proxy, which completes first.
4150 session_deps_.host_resolver->set_ondemand_mode(false);
4151 SpdySessionKey key(
4152 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
4153 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:424154 CreateSecureSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:504155
4156 // Unstall the resolution begun by the transaction.
4157 session_deps_.host_resolver->set_ondemand_mode(true);
4158 session_deps_.host_resolver->ResolveAllPending();
4159
4160 EXPECT_FALSE(callback1.have_result());
4161 rv = callback1.WaitForResult();
4162 EXPECT_EQ(OK, rv);
4163
4164 const HttpResponseInfo* response = trans->GetResponseInfo();
4165 ASSERT_TRUE(response != NULL);
4166 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024167 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:504168
4169 std::string response_data;
4170 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4171 EXPECT_EQ(kUploadData, response_data);
4172}
4173
[email protected]dc7bd1c52010-11-12 00:01:134174// Test a SPDY get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024175TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:274176 HttpRequestInfo request;
4177 request.method = "GET";
bncce36dca22015-04-21 22:11:234178 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274179 request.load_flags = 0;
4180
[email protected]79cb5c12011-09-12 13:12:044181 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034182 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:514183 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074184 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424185 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:134186
[email protected]dc7bd1c52010-11-12 00:01:134187 // The first request will be a bare GET, the second request will be a
4188 // GET with a Proxy-Authorization header.
[email protected]ff98d7f02012-03-22 21:44:194189 scoped_ptr<SpdyFrame> req_get(
[email protected]cdf8f7e72013-05-23 10:56:464190 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rdsmithebb50aa2015-11-12 03:44:384191 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:134192 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464193 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:134194 };
[email protected]ff98d7f02012-03-22 21:44:194195 scoped_ptr<SpdyFrame> req_get_authorization(
[email protected]cdf8f7e72013-05-23 10:56:464196 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4197 arraysize(kExtraAuthorizationHeaders) / 2,
4198 false,
4199 3,
4200 LOWEST,
4201 false));
[email protected]dc7bd1c52010-11-12 00:01:134202 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134203 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:134204 };
4205
4206 // The first response is a 407 proxy authentication challenge, and the second
4207 // response will be a 200 response since the second request includes a valid
4208 // Authorization header.
4209 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464210 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:134211 };
[email protected]ff98d7f02012-03-22 21:44:194212 scoped_ptr<SpdyFrame> resp_authentication(
[email protected]23e482282013-06-14 16:08:024213 spdy_util_.ConstructSpdySynReplyError(
[email protected]dc7bd1c52010-11-12 00:01:134214 "407 Proxy Authentication Required",
4215 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
4216 1));
[email protected]ff98d7f02012-03-22 21:44:194217 scoped_ptr<SpdyFrame> body_authentication(
[email protected]23e482282013-06-14 16:08:024218 spdy_util_.ConstructSpdyBodyFrame(1, true));
4219 scoped_ptr<SpdyFrame> resp_data(
4220 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4221 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:134222 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134223 CreateMockRead(*resp_authentication, 1),
4224 CreateMockRead(*body_authentication, 2),
4225 CreateMockRead(*resp_data, 4),
4226 CreateMockRead(*body_data, 5),
4227 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:134228 };
4229
rch8e6c6c42015-05-01 14:05:134230 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4231 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074232 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:134233
[email protected]8ddf8322012-02-23 18:08:064234 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384235 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074236 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:134237
[email protected]49639fa2011-12-20 23:22:414238 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:134239
[email protected]262eec82013-03-19 21:01:364240 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504241 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]dc7bd1c52010-11-12 00:01:134242
[email protected]49639fa2011-12-20 23:22:414243 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]dc7bd1c52010-11-12 00:01:134244 EXPECT_EQ(ERR_IO_PENDING, rv);
4245
4246 rv = callback1.WaitForResult();
4247 EXPECT_EQ(OK, rv);
4248
4249 const HttpResponseInfo* const response = trans->GetResponseInfo();
4250
4251 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504252 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]dc7bd1c52010-11-12 00:01:134253 EXPECT_EQ(407, response->headers->response_code());
4254 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:044255 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]dc7bd1c52010-11-12 00:01:134256
[email protected]49639fa2011-12-20 23:22:414257 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:134258
[email protected]49639fa2011-12-20 23:22:414259 rv = trans->RestartWithAuth(
4260 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]dc7bd1c52010-11-12 00:01:134261 EXPECT_EQ(ERR_IO_PENDING, rv);
4262
4263 rv = callback2.WaitForResult();
4264 EXPECT_EQ(OK, rv);
4265
4266 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4267
4268 ASSERT_TRUE(response_restart != NULL);
[email protected]90499482013-06-01 00:39:504269 ASSERT_TRUE(response_restart->headers.get() != NULL);
[email protected]dc7bd1c52010-11-12 00:01:134270 EXPECT_EQ(200, response_restart->headers->response_code());
4271 // The password prompt info should not be set.
4272 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4273}
4274
[email protected]d9da5fe2010-10-13 22:37:164275// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
[email protected]23e482282013-06-14 16:08:024276TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:274277 HttpRequestInfo request;
4278 request.method = "GET";
bncce36dca22015-04-21 22:11:234279 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274280 request.load_flags = 0;
4281
[email protected]d9da5fe2010-10-13 22:37:164282 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034283 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514284 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074285 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424286 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164287
[email protected]262eec82013-03-19 21:01:364288 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504289 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164290
bncce36dca22015-04-21 22:11:234291 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344292 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234293 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
4294 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:164295
bncce36dca22015-04-21 22:11:234296 const char get[] =
4297 "GET / HTTP/1.1\r\n"
4298 "Host: www.example.org\r\n"
4299 "Connection: keep-alive\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:194300 scoped_ptr<SpdyFrame> wrapped_get(
[email protected]23e482282013-06-14 16:08:024301 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
4302 scoped_ptr<SpdyFrame> conn_resp(
4303 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:164304 const char resp[] = "HTTP/1.1 200 OK\r\n"
4305 "Content-Length: 10\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:194306 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:024307 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
[email protected]ff98d7f02012-03-22 21:44:194308 scoped_ptr<SpdyFrame> wrapped_body(
[email protected]23e482282013-06-14 16:08:024309 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
[email protected]ff98d7f02012-03-22 21:44:194310 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204311 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
[email protected]8d2f7012012-02-16 00:08:044312
4313 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134314 CreateMockWrite(*connect, 0),
4315 CreateMockWrite(*wrapped_get, 2),
4316 CreateMockWrite(*window_update, 6),
[email protected]8d2f7012012-02-16 00:08:044317 };
4318
[email protected]d9da5fe2010-10-13 22:37:164319 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134320 CreateMockRead(*conn_resp, 1, ASYNC),
4321 CreateMockRead(*wrapped_get_resp, 3, ASYNC),
4322 CreateMockRead(*wrapped_body, 4, ASYNC),
4323 CreateMockRead(*wrapped_body, 5, ASYNC),
4324 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:164325 };
4326
rch8e6c6c42015-05-01 14:05:134327 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4328 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074329 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164330
[email protected]8ddf8322012-02-23 18:08:064331 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384332 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074333 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064334 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074335 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164336
[email protected]49639fa2011-12-20 23:22:414337 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164338
[email protected]49639fa2011-12-20 23:22:414339 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164340 EXPECT_EQ(ERR_IO_PENDING, rv);
4341
4342 rv = callback1.WaitForResult();
rch8e6c6c42015-05-01 14:05:134343 ASSERT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:164344
[email protected]58e32bb2013-01-21 18:23:254345 LoadTimingInfo load_timing_info;
4346 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4347 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4348
[email protected]d9da5fe2010-10-13 22:37:164349 const HttpResponseInfo* response = trans->GetResponseInfo();
4350 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504351 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]d9da5fe2010-10-13 22:37:164352 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4353
4354 std::string response_data;
4355 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4356 EXPECT_EQ("1234567890", response_data);
4357}
4358
4359// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
[email protected]23e482282013-06-14 16:08:024360TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
rdsmithebb50aa2015-11-12 03:44:384361 SpdyTestUtil spdy_util_wrapped(GetProtocol(), GetDependenciesFromPriority());
4362
[email protected]cb9bf6ca2011-01-28 13:15:274363 HttpRequestInfo request;
4364 request.method = "GET";
bncce36dca22015-04-21 22:11:234365 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274366 request.load_flags = 0;
4367
[email protected]d9da5fe2010-10-13 22:37:164368 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034369 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514370 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074371 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424372 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164373
[email protected]262eec82013-03-19 21:01:364374 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504375 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164376
bncce36dca22015-04-21 22:11:234377 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344378 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234379 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
4380 // fetch https://www.example.org/ via SPDY
4381 const char kMyUrl[] = "https://www.example.org/";
[email protected]cdf8f7e72013-05-23 10:56:464382 scoped_ptr<SpdyFrame> get(
rdsmithebb50aa2015-11-12 03:44:384383 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
[email protected]23e482282013-06-14 16:08:024384 scoped_ptr<SpdyFrame> wrapped_get(
4385 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
4386 scoped_ptr<SpdyFrame> conn_resp(
4387 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4388 scoped_ptr<SpdyFrame> get_resp(
rdsmithebb50aa2015-11-12 03:44:384389 spdy_util_wrapped.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:194390 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:024391 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
rdsmithebb50aa2015-11-12 03:44:384392 scoped_ptr<SpdyFrame> body(spdy_util_wrapped.ConstructSpdyBodyFrame(1, true));
[email protected]23e482282013-06-14 16:08:024393 scoped_ptr<SpdyFrame> wrapped_body(
4394 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
[email protected]ff98d7f02012-03-22 21:44:194395 scoped_ptr<SpdyFrame> window_update_get_resp(
[email protected]c10b20852013-05-15 21:29:204396 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
[email protected]ff98d7f02012-03-22 21:44:194397 scoped_ptr<SpdyFrame> window_update_body(
[email protected]c10b20852013-05-15 21:29:204398 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
[email protected]8d2f7012012-02-16 00:08:044399
4400 MockWrite spdy_writes[] = {
rch32320842015-05-16 15:57:094401 CreateMockWrite(*connect, 0),
4402 CreateMockWrite(*wrapped_get, 2),
4403 CreateMockWrite(*window_update_get_resp, 6),
[email protected]8d2f7012012-02-16 00:08:044404 CreateMockWrite(*window_update_body, 7),
4405 };
4406
[email protected]d9da5fe2010-10-13 22:37:164407 MockRead spdy_reads[] = {
rch32320842015-05-16 15:57:094408 CreateMockRead(*conn_resp, 1, ASYNC),
4409 MockRead(ASYNC, ERR_IO_PENDING, 3),
rch8e6c6c42015-05-01 14:05:134410 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
rch32320842015-05-16 15:57:094411 CreateMockRead(*wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:134412 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:164413 };
4414
rch32320842015-05-16 15:57:094415 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4416 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074417 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164418
[email protected]8ddf8322012-02-23 18:08:064419 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384420 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074421 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064422 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384423 ssl2.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074424 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164425
[email protected]49639fa2011-12-20 23:22:414426 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164427
[email protected]49639fa2011-12-20 23:22:414428 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164429 EXPECT_EQ(ERR_IO_PENDING, rv);
4430
rch32320842015-05-16 15:57:094431 // Allow the SpdyProxyClientSocket's write callback to complete.
4432 base::MessageLoop::current()->RunUntilIdle();
4433 // Now allow the read of the response to complete.
4434 spdy_data.CompleteRead();
[email protected]d9da5fe2010-10-13 22:37:164435 rv = callback1.WaitForResult();
4436 EXPECT_EQ(OK, rv);
4437
[email protected]58e32bb2013-01-21 18:23:254438 LoadTimingInfo load_timing_info;
4439 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4440 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4441
[email protected]d9da5fe2010-10-13 22:37:164442 const HttpResponseInfo* response = trans->GetResponseInfo();
4443 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504444 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024445 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:164446
4447 std::string response_data;
4448 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]448d4ca52012-03-04 04:12:234449 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:164450}
4451
4452// Test a SPDY CONNECT failure through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024453TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:274454 HttpRequestInfo request;
4455 request.method = "GET";
bncce36dca22015-04-21 22:11:234456 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274457 request.load_flags = 0;
4458
[email protected]d9da5fe2010-10-13 22:37:164459 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034460 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514461 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074462 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424463 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164464
[email protected]262eec82013-03-19 21:01:364465 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504466 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164467
bncce36dca22015-04-21 22:11:234468 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344469 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234470 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:204471 scoped_ptr<SpdyFrame> get(
4472 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:164473
4474 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134475 CreateMockWrite(*connect, 0), CreateMockWrite(*get, 2),
[email protected]d9da5fe2010-10-13 22:37:164476 };
4477
[email protected]23e482282013-06-14 16:08:024478 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
4479 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:164480 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134481 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:164482 };
4483
rch8e6c6c42015-05-01 14:05:134484 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4485 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074486 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164487
[email protected]8ddf8322012-02-23 18:08:064488 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384489 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074490 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064491 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384492 ssl2.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074493 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164494
[email protected]49639fa2011-12-20 23:22:414495 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164496
[email protected]49639fa2011-12-20 23:22:414497 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164498 EXPECT_EQ(ERR_IO_PENDING, rv);
4499
4500 rv = callback1.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:174501 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]d9da5fe2010-10-13 22:37:164502
[email protected]4eddbc732012-08-09 05:40:174503 // TODO(ttuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:164504}
4505
[email protected]f6c63db52013-02-02 00:35:224506// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4507// HTTPS Proxy to different servers.
[email protected]23e482282013-06-14 16:08:024508TEST_P(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:224509 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
4510 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034511 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514512 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074513 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424514 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504515 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224516
4517 HttpRequestInfo request1;
4518 request1.method = "GET";
bncce36dca22015-04-21 22:11:234519 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224520 request1.load_flags = 0;
4521
4522 HttpRequestInfo request2;
4523 request2.method = "GET";
bncce36dca22015-04-21 22:11:234524 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:224525 request2.load_flags = 0;
4526
bncce36dca22015-04-21 22:11:234527 // CONNECT to www.example.org:443 via SPDY.
lgarrona91df87f2014-12-05 00:51:344528 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234529 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]23e482282013-06-14 16:08:024530 scoped_ptr<SpdyFrame> conn_resp1(
4531 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f6c63db52013-02-02 00:35:224532
bncce36dca22015-04-21 22:11:234533 // Fetch https://www.example.org/ via HTTP.
4534 const char get1[] =
4535 "GET / HTTP/1.1\r\n"
4536 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224537 "Connection: keep-alive\r\n\r\n";
4538 scoped_ptr<SpdyFrame> wrapped_get1(
[email protected]23e482282013-06-14 16:08:024539 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
[email protected]f6c63db52013-02-02 00:35:224540 const char resp1[] = "HTTP/1.1 200 OK\r\n"
4541 "Content-Length: 1\r\n\r\n";
4542 scoped_ptr<SpdyFrame> wrapped_get_resp1(
[email protected]23e482282013-06-14 16:08:024543 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
4544 scoped_ptr<SpdyFrame> wrapped_body1(
4545 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
[email protected]f6c63db52013-02-02 00:35:224546 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204547 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
[email protected]f6c63db52013-02-02 00:35:224548
bncce36dca22015-04-21 22:11:234549 // CONNECT to mail.example.org:443 via SPDY.
[email protected]745aa9c2014-06-27 02:21:294550 SpdyHeaderBlock connect2_block;
bnc7ecc1122015-09-28 13:22:494551 spdy_util_.MaybeAddVersionHeader(&connect2_block);
[email protected]745aa9c2014-06-27 02:21:294552 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
rdsmithebb50aa2015-11-12 03:44:384553 if (GetProtocol() == kProtoHTTP2) {
bnc6b996d532015-07-29 10:51:324554 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org:443";
4555 } else {
bnc6b996d532015-07-29 10:51:324556 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org";
bnc7ecc1122015-09-28 13:22:494557 connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443";
bnc6b996d532015-07-29 10:51:324558 }
[email protected]f6c63db52013-02-02 00:35:224559 scoped_ptr<SpdyFrame> connect2(
[email protected]745aa9c2014-06-27 02:21:294560 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
[email protected]601e03f12014-04-06 16:26:394561
[email protected]23e482282013-06-14 16:08:024562 scoped_ptr<SpdyFrame> conn_resp2(
4563 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]f6c63db52013-02-02 00:35:224564
bncce36dca22015-04-21 22:11:234565 // Fetch https://mail.example.org/ via HTTP.
4566 const char get2[] =
4567 "GET / HTTP/1.1\r\n"
4568 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224569 "Connection: keep-alive\r\n\r\n";
4570 scoped_ptr<SpdyFrame> wrapped_get2(
[email protected]23e482282013-06-14 16:08:024571 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
[email protected]f6c63db52013-02-02 00:35:224572 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4573 "Content-Length: 2\r\n\r\n";
4574 scoped_ptr<SpdyFrame> wrapped_get_resp2(
[email protected]23e482282013-06-14 16:08:024575 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
[email protected]f6c63db52013-02-02 00:35:224576 scoped_ptr<SpdyFrame> wrapped_body2(
[email protected]23e482282013-06-14 16:08:024577 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
[email protected]f6c63db52013-02-02 00:35:224578
4579 MockWrite spdy_writes[] = {
4580 CreateMockWrite(*connect1, 0),
4581 CreateMockWrite(*wrapped_get1, 2),
4582 CreateMockWrite(*connect2, 5),
4583 CreateMockWrite(*wrapped_get2, 7),
4584 };
4585
4586 MockRead spdy_reads[] = {
4587 CreateMockRead(*conn_resp1, 1, ASYNC),
4588 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4589 CreateMockRead(*wrapped_body1, 4, ASYNC),
4590 CreateMockRead(*conn_resp2, 6, ASYNC),
4591 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
4592 CreateMockRead(*wrapped_body2, 9, ASYNC),
4593 MockRead(ASYNC, 0, 10),
4594 };
4595
mmenke11eb5152015-06-09 14:50:504596 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4597 arraysize(spdy_writes));
4598 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224599
4600 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384601 ssl.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:504602 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224603 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504604 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:224605 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504606 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:224607
4608 TestCompletionCallback callback;
4609
[email protected]262eec82013-03-19 21:01:364610 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504611 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224612 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504613 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224614
4615 LoadTimingInfo load_timing_info;
4616 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4617 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4618
4619 const HttpResponseInfo* response = trans->GetResponseInfo();
4620 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504621 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]f6c63db52013-02-02 00:35:224622 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4623
4624 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:294625 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
mmenke11eb5152015-06-09 14:50:504626 rv = trans->Read(buf.get(), 256, callback.callback());
4627 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224628
[email protected]262eec82013-03-19 21:01:364629 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504630 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224631 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504632 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224633
4634 LoadTimingInfo load_timing_info2;
4635 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4636 // Even though the SPDY connection is reused, a new tunnelled connection has
4637 // to be created, so the socket's load timing looks like a fresh connection.
4638 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
4639
4640 // The requests should have different IDs, since they each are using their own
4641 // separate stream.
4642 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4643
mmenke11eb5152015-06-09 14:50:504644 rv = trans2->Read(buf.get(), 256, callback.callback());
4645 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224646}
4647
4648// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4649// HTTPS Proxy to the same server.
[email protected]23e482282013-06-14 16:08:024650TEST_P(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:224651 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
4652 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034653 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514654 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074655 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424656 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504657 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224658
4659 HttpRequestInfo request1;
4660 request1.method = "GET";
bncce36dca22015-04-21 22:11:234661 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224662 request1.load_flags = 0;
4663
4664 HttpRequestInfo request2;
4665 request2.method = "GET";
bncce36dca22015-04-21 22:11:234666 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:224667 request2.load_flags = 0;
4668
bncce36dca22015-04-21 22:11:234669 // CONNECT to www.example.org:443 via SPDY.
lgarrona91df87f2014-12-05 00:51:344670 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234671 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]23e482282013-06-14 16:08:024672 scoped_ptr<SpdyFrame> conn_resp1(
4673 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f6c63db52013-02-02 00:35:224674
bncce36dca22015-04-21 22:11:234675 // Fetch https://www.example.org/ via HTTP.
4676 const char get1[] =
4677 "GET / HTTP/1.1\r\n"
4678 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224679 "Connection: keep-alive\r\n\r\n";
4680 scoped_ptr<SpdyFrame> wrapped_get1(
[email protected]23e482282013-06-14 16:08:024681 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
[email protected]f6c63db52013-02-02 00:35:224682 const char resp1[] = "HTTP/1.1 200 OK\r\n"
4683 "Content-Length: 1\r\n\r\n";
4684 scoped_ptr<SpdyFrame> wrapped_get_resp1(
[email protected]23e482282013-06-14 16:08:024685 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
4686 scoped_ptr<SpdyFrame> wrapped_body1(
4687 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
[email protected]f6c63db52013-02-02 00:35:224688 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204689 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
[email protected]f6c63db52013-02-02 00:35:224690
bncce36dca22015-04-21 22:11:234691 // Fetch https://www.example.org/2 via HTTP.
4692 const char get2[] =
4693 "GET /2 HTTP/1.1\r\n"
4694 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224695 "Connection: keep-alive\r\n\r\n";
4696 scoped_ptr<SpdyFrame> wrapped_get2(
[email protected]23e482282013-06-14 16:08:024697 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
[email protected]f6c63db52013-02-02 00:35:224698 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4699 "Content-Length: 2\r\n\r\n";
4700 scoped_ptr<SpdyFrame> wrapped_get_resp2(
[email protected]23e482282013-06-14 16:08:024701 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
[email protected]f6c63db52013-02-02 00:35:224702 scoped_ptr<SpdyFrame> wrapped_body2(
[email protected]23e482282013-06-14 16:08:024703 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
[email protected]f6c63db52013-02-02 00:35:224704
4705 MockWrite spdy_writes[] = {
4706 CreateMockWrite(*connect1, 0),
4707 CreateMockWrite(*wrapped_get1, 2),
4708 CreateMockWrite(*wrapped_get2, 5),
4709 };
4710
4711 MockRead spdy_reads[] = {
4712 CreateMockRead(*conn_resp1, 1, ASYNC),
4713 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4714 CreateMockRead(*wrapped_body1, 4, ASYNC),
4715 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
4716 CreateMockRead(*wrapped_body2, 7, ASYNC),
4717 MockRead(ASYNC, 0, 8),
4718 };
4719
mmenke11eb5152015-06-09 14:50:504720 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4721 arraysize(spdy_writes));
4722 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224723
4724 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384725 ssl.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:504726 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224727 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504728 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:224729
4730 TestCompletionCallback callback;
4731
[email protected]262eec82013-03-19 21:01:364732 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504733 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224734 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4735 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f6c63db52013-02-02 00:35:224736
4737 rv = callback.WaitForResult();
4738 EXPECT_EQ(OK, rv);
4739
4740 LoadTimingInfo load_timing_info;
4741 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4742 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4743
4744 const HttpResponseInfo* response = trans->GetResponseInfo();
4745 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504746 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]f6c63db52013-02-02 00:35:224747 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4748
4749 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:294750 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
[email protected]90499482013-06-01 00:39:504751 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:224752 trans.reset();
4753
[email protected]262eec82013-03-19 21:01:364754 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504755 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224756 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4757 EXPECT_EQ(ERR_IO_PENDING, rv);
4758
[email protected]f6c63db52013-02-02 00:35:224759 rv = callback.WaitForResult();
4760 EXPECT_EQ(OK, rv);
4761
4762 LoadTimingInfo load_timing_info2;
4763 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4764 TestLoadTimingReused(load_timing_info2);
4765
4766 // The requests should have the same ID.
4767 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4768
[email protected]90499482013-06-01 00:39:504769 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:224770}
4771
4772// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4773// Proxy to different servers.
mmenke11eb5152015-06-09 14:50:504774TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:224775 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034776 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514777 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074778 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424779 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504780 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224781
4782 HttpRequestInfo request1;
4783 request1.method = "GET";
bncce36dca22015-04-21 22:11:234784 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224785 request1.load_flags = 0;
4786
4787 HttpRequestInfo request2;
4788 request2.method = "GET";
bncce36dca22015-04-21 22:11:234789 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:224790 request2.load_flags = 0;
4791
bncce36dca22015-04-21 22:11:234792 // http://www.example.org/
[email protected]23e482282013-06-14 16:08:024793 scoped_ptr<SpdyHeaderBlock> headers(
bncce36dca22015-04-21 22:11:234794 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
[email protected]745aa9c2014-06-27 02:21:294795 scoped_ptr<SpdyFrame> get1(
4796 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]23e482282013-06-14 16:08:024797 scoped_ptr<SpdyFrame> get_resp1(
4798 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4799 scoped_ptr<SpdyFrame> body1(
4800 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
rdsmithebb50aa2015-11-12 03:44:384801 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:224802
bncce36dca22015-04-21 22:11:234803 // http://mail.example.org/
[email protected]23e482282013-06-14 16:08:024804 scoped_ptr<SpdyHeaderBlock> headers2(
bncce36dca22015-04-21 22:11:234805 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
[email protected]745aa9c2014-06-27 02:21:294806 scoped_ptr<SpdyFrame> get2(
4807 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
[email protected]23e482282013-06-14 16:08:024808 scoped_ptr<SpdyFrame> get_resp2(
4809 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4810 scoped_ptr<SpdyFrame> body2(
4811 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
[email protected]f6c63db52013-02-02 00:35:224812
4813 MockWrite spdy_writes[] = {
4814 CreateMockWrite(*get1, 0),
4815 CreateMockWrite(*get2, 3),
4816 };
4817
4818 MockRead spdy_reads[] = {
4819 CreateMockRead(*get_resp1, 1, ASYNC),
4820 CreateMockRead(*body1, 2, ASYNC),
4821 CreateMockRead(*get_resp2, 4, ASYNC),
4822 CreateMockRead(*body2, 5, ASYNC),
4823 MockRead(ASYNC, 0, 6),
4824 };
4825
mmenke11eb5152015-06-09 14:50:504826 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4827 arraysize(spdy_writes));
4828 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224829
4830 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384831 ssl.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:504832 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224833
4834 TestCompletionCallback callback;
4835
[email protected]262eec82013-03-19 21:01:364836 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504837 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224838 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504839 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224840
4841 LoadTimingInfo load_timing_info;
4842 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4843 TestLoadTimingNotReused(load_timing_info,
4844 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4845
4846 const HttpResponseInfo* response = trans->GetResponseInfo();
4847 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504848 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024849 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:224850
4851 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:294852 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
mmenke11eb5152015-06-09 14:50:504853 rv = trans->Read(buf.get(), 256, callback.callback());
4854 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224855 // Delete the first request, so the second one can reuse the socket.
4856 trans.reset();
4857
[email protected]262eec82013-03-19 21:01:364858 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504859 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224860 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504861 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224862
4863 LoadTimingInfo load_timing_info2;
4864 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4865 TestLoadTimingReused(load_timing_info2);
4866
4867 // The requests should have the same ID.
4868 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4869
mmenke11eb5152015-06-09 14:50:504870 rv = trans2->Read(buf.get(), 256, callback.callback());
4871 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224872}
4873
[email protected]2df19bb2010-08-25 20:13:464874// Test the challenge-response-retry sequence through an HTTPS Proxy
[email protected]23e482282013-06-14 16:08:024875TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:464876 HttpRequestInfo request;
4877 request.method = "GET";
bncce36dca22015-04-21 22:11:234878 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:464879 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:294880 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2df19bb2010-08-25 20:13:464881
[email protected]79cb5c12011-09-12 13:12:044882 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034883 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:514884 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074885 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424886 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:274887
[email protected]2df19bb2010-08-25 20:13:464888 // Since we have proxy, should use full url
4889 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234890 MockWrite(
4891 "GET http://www.example.org/ HTTP/1.1\r\n"
4892 "Host: www.example.org\r\n"
4893 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:464894
bncce36dca22015-04-21 22:11:234895 // After calling trans->RestartWithAuth(), this is the request we should
4896 // be issuing -- the final header line contains the credentials.
4897 MockWrite(
4898 "GET http://www.example.org/ HTTP/1.1\r\n"
4899 "Host: www.example.org\r\n"
4900 "Proxy-Connection: keep-alive\r\n"
4901 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:464902 };
4903
4904 // The proxy responds to the GET with a 407, using a persistent
4905 // connection.
4906 MockRead data_reads1[] = {
4907 // No credentials.
4908 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4909 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4910 MockRead("Proxy-Connection: keep-alive\r\n"),
4911 MockRead("Content-Length: 0\r\n\r\n"),
4912
4913 MockRead("HTTP/1.1 200 OK\r\n"),
4914 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4915 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064916 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:464917 };
4918
4919 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4920 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074921 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064922 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074923 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:464924
[email protected]49639fa2011-12-20 23:22:414925 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:464926
[email protected]262eec82013-03-19 21:01:364927 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504928 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504929
[email protected]49639fa2011-12-20 23:22:414930 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:464931 EXPECT_EQ(ERR_IO_PENDING, rv);
4932
4933 rv = callback1.WaitForResult();
4934 EXPECT_EQ(OK, rv);
4935
[email protected]58e32bb2013-01-21 18:23:254936 LoadTimingInfo load_timing_info;
4937 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4938 TestLoadTimingNotReused(load_timing_info,
4939 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4940
[email protected]2df19bb2010-08-25 20:13:464941 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504942 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504943 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]2df19bb2010-08-25 20:13:464944 EXPECT_EQ(407, response->headers->response_code());
4945 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:044946 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2df19bb2010-08-25 20:13:464947
[email protected]49639fa2011-12-20 23:22:414948 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:464949
[email protected]49639fa2011-12-20 23:22:414950 rv = trans->RestartWithAuth(
4951 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]2df19bb2010-08-25 20:13:464952 EXPECT_EQ(ERR_IO_PENDING, rv);
4953
4954 rv = callback2.WaitForResult();
4955 EXPECT_EQ(OK, rv);
4956
[email protected]58e32bb2013-01-21 18:23:254957 load_timing_info = LoadTimingInfo();
4958 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4959 // Retrying with HTTP AUTH is considered to be reusing a socket.
4960 TestLoadTimingReused(load_timing_info);
4961
[email protected]2df19bb2010-08-25 20:13:464962 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504963 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464964
4965 EXPECT_TRUE(response->headers->IsKeepAlive());
4966 EXPECT_EQ(200, response->headers->response_code());
4967 EXPECT_EQ(100, response->headers->GetContentLength());
4968 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4969
4970 // The password prompt info should not be set.
4971 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4972}
4973
[email protected]23e482282013-06-14 16:08:024974void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:084975 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:424976 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:084977 request.method = "GET";
bncce36dca22015-04-21 22:11:234978 request.url = GURL("https://www.example.org/");
[email protected]c744cf22009-02-27 07:28:084979 request.load_flags = 0;
4980
[email protected]cb9bf6ca2011-01-28 13:15:274981 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034982 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:424983 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:274984
[email protected]c744cf22009-02-27 07:28:084985 // Since we have proxy, should try to establish tunnel.
4986 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174987 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4988 "Host: www.example.org:443\r\n"
4989 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:084990 };
4991
4992 MockRead data_reads[] = {
4993 status,
4994 MockRead("Content-Length: 10\r\n\r\n"),
4995 // No response body because the test stops reading here.
[email protected]8ddf8322012-02-23 18:08:064996 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:084997 };
4998
[email protected]31a2bfe2010-02-09 08:03:394999 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5000 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:075001 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:085002
[email protected]49639fa2011-12-20 23:22:415003 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:085004
[email protected]262eec82013-03-19 21:01:365005 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505006 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505007
[email protected]49639fa2011-12-20 23:22:415008 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425009 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:085010
5011 rv = callback.WaitForResult();
5012 EXPECT_EQ(expected_status, rv);
5013}
5014
[email protected]23e482282013-06-14 16:08:025015void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:235016 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:085017 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:425018 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:085019}
5020
[email protected]23e482282013-06-14 16:08:025021TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:085022 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
5023}
5024
[email protected]23e482282013-06-14 16:08:025025TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:085026 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
5027}
5028
[email protected]23e482282013-06-14 16:08:025029TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:085030 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
5031}
5032
[email protected]23e482282013-06-14 16:08:025033TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:085034 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
5035}
5036
[email protected]23e482282013-06-14 16:08:025037TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:085038 ConnectStatusHelper(
5039 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
5040}
5041
[email protected]23e482282013-06-14 16:08:025042TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:085043 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
5044}
5045
[email protected]23e482282013-06-14 16:08:025046TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:085047 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
5048}
5049
[email protected]23e482282013-06-14 16:08:025050TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:085051 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
5052}
5053
[email protected]23e482282013-06-14 16:08:025054TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:085055 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
5056}
5057
[email protected]23e482282013-06-14 16:08:025058TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:085059 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
5060}
5061
[email protected]23e482282013-06-14 16:08:025062TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:085063 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
5064}
5065
[email protected]23e482282013-06-14 16:08:025066TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:085067 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
5068}
5069
[email protected]23e482282013-06-14 16:08:025070TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:085071 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
5072}
5073
[email protected]23e482282013-06-14 16:08:025074TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:085075 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
5076}
5077
[email protected]23e482282013-06-14 16:08:025078TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:085079 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
5080}
5081
[email protected]23e482282013-06-14 16:08:025082TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:085083 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
5084}
5085
[email protected]0a17aab32014-04-24 03:32:375086TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
5087 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
5088}
5089
[email protected]23e482282013-06-14 16:08:025090TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:085091 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
5092}
5093
[email protected]23e482282013-06-14 16:08:025094TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:085095 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
5096}
5097
[email protected]23e482282013-06-14 16:08:025098TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:085099 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
5100}
5101
[email protected]23e482282013-06-14 16:08:025102TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:085103 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
5104}
5105
[email protected]23e482282013-06-14 16:08:025106TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:085107 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
5108}
5109
[email protected]23e482282013-06-14 16:08:025110TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:085111 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
5112}
5113
[email protected]23e482282013-06-14 16:08:025114TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:085115 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
5116}
5117
[email protected]23e482282013-06-14 16:08:025118TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:085119 ConnectStatusHelperWithExpectedStatus(
5120 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:545121 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:085122}
5123
[email protected]23e482282013-06-14 16:08:025124TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:085125 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
5126}
5127
[email protected]23e482282013-06-14 16:08:025128TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:085129 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
5130}
5131
[email protected]23e482282013-06-14 16:08:025132TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:085133 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
5134}
5135
[email protected]23e482282013-06-14 16:08:025136TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:085137 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
5138}
5139
[email protected]23e482282013-06-14 16:08:025140TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:085141 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
5142}
5143
[email protected]23e482282013-06-14 16:08:025144TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:085145 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
5146}
5147
[email protected]23e482282013-06-14 16:08:025148TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:085149 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
5150}
5151
[email protected]23e482282013-06-14 16:08:025152TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:085153 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
5154}
5155
[email protected]23e482282013-06-14 16:08:025156TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:085157 ConnectStatusHelper(
5158 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
5159}
5160
[email protected]23e482282013-06-14 16:08:025161TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:085162 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
5163}
5164
[email protected]23e482282013-06-14 16:08:025165TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:085166 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
5167}
5168
[email protected]23e482282013-06-14 16:08:025169TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:085170 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
5171}
5172
[email protected]23e482282013-06-14 16:08:025173TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:085174 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
5175}
5176
[email protected]23e482282013-06-14 16:08:025177TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:085178 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
5179}
5180
[email protected]23e482282013-06-14 16:08:025181TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:085182 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
5183}
5184
[email protected]23e482282013-06-14 16:08:025185TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:085186 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
5187}
5188
[email protected]038e9a32008-10-08 22:40:165189// Test the flow when both the proxy server AND origin server require
5190// authentication. Again, this uses basic auth for both since that is
5191// the simplest to mock.
[email protected]23e482282013-06-14 16:08:025192TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:275193 HttpRequestInfo request;
5194 request.method = "GET";
bncce36dca22015-04-21 22:11:235195 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:275196 request.load_flags = 0;
5197
[email protected]038e9a32008-10-08 22:40:165198 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035199 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:425200 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:075201
5202 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:415203 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]038e9a32008-10-08 22:40:165204
[email protected]f9ee6b52008-11-08 06:46:235205 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235206 MockWrite(
5207 "GET http://www.example.org/ HTTP/1.1\r\n"
5208 "Host: www.example.org\r\n"
5209 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:235210 };
5211
[email protected]038e9a32008-10-08 22:40:165212 MockRead data_reads1[] = {
5213 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
5214 // Give a couple authenticate options (only the middle one is actually
5215 // supported).
[email protected]22927ad2009-09-21 19:56:195216 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:165217 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5218 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
5219 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5220 // Large content-length -- won't matter, as connection will be reset.
5221 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065222 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:165223 };
5224
5225 // After calling trans->RestartWithAuth() the first time, this is the
5226 // request we should be issuing -- the final header line contains the
5227 // proxy's credentials.
5228 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:235229 MockWrite(
5230 "GET http://www.example.org/ HTTP/1.1\r\n"
5231 "Host: www.example.org\r\n"
5232 "Proxy-Connection: keep-alive\r\n"
5233 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:165234 };
5235
5236 // Now the proxy server lets the request pass through to origin server.
5237 // The origin server responds with a 401.
5238 MockRead data_reads2[] = {
5239 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5240 // Note: We are using the same realm-name as the proxy server. This is
5241 // completely valid, as realms are unique across hosts.
5242 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5243 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5244 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065245 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:165246 };
5247
5248 // After calling trans->RestartWithAuth() the second time, we should send
5249 // the credentials for both the proxy and origin server.
5250 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:235251 MockWrite(
5252 "GET http://www.example.org/ HTTP/1.1\r\n"
5253 "Host: www.example.org\r\n"
5254 "Proxy-Connection: keep-alive\r\n"
5255 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
5256 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:165257 };
5258
5259 // Lastly we get the desired content.
5260 MockRead data_reads3[] = {
5261 MockRead("HTTP/1.0 200 OK\r\n"),
5262 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5263 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065264 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:165265 };
5266
[email protected]31a2bfe2010-02-09 08:03:395267 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5268 data_writes1, arraysize(data_writes1));
5269 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5270 data_writes2, arraysize(data_writes2));
5271 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5272 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:075273 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5274 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5275 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:165276
[email protected]49639fa2011-12-20 23:22:415277 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:165278
[email protected]49639fa2011-12-20 23:22:415279 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425280 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165281
5282 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425283 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165284
[email protected]1c773ea12009-04-28 19:58:425285 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505286 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045287 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:165288
[email protected]49639fa2011-12-20 23:22:415289 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:165290
[email protected]49639fa2011-12-20 23:22:415291 rv = trans->RestartWithAuth(
5292 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:425293 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165294
5295 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425296 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165297
5298 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505299 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045300 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:165301
[email protected]49639fa2011-12-20 23:22:415302 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:165303
[email protected]49639fa2011-12-20 23:22:415304 rv = trans->RestartWithAuth(
5305 AuthCredentials(kFoo2, kBar2), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425306 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165307
5308 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425309 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165310
5311 response = trans->GetResponseInfo();
5312 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5313 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:165314}
[email protected]4ddaf2502008-10-23 18:26:195315
[email protected]ea9dc9a2009-09-05 00:43:325316// For the NTLM implementation using SSPI, we skip the NTLM tests since we
5317// can't hook into its internals to cause it to generate predictable NTLM
5318// authorization headers.
5319#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:295320// The NTLM authentication unit tests were generated by capturing the HTTP
5321// requests and responses using Fiddler 2 and inspecting the generated random
5322// bytes in the debugger.
5323
5324// Enter the correct password and authenticate successfully.
[email protected]23e482282013-06-14 16:08:025325TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:425326 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:245327 request.method = "GET";
5328 request.url = GURL("http://172.22.68.17/kids/login.aspx");
[email protected]2217aa22013-10-11 03:03:545329
5330 // Ensure load is not disrupted by flags which suppress behaviour specific
5331 // to other auth schemes.
5332 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:245333
[email protected]cb9bf6ca2011-01-28 13:15:275334 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
5335 MockGetHostName);
mmenkee65e7af2015-10-13 17:16:425336 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275337
[email protected]3f918782009-02-28 01:29:245338 MockWrite data_writes1[] = {
5339 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5340 "Host: 172.22.68.17\r\n"
5341 "Connection: keep-alive\r\n\r\n"),
5342 };
5343
5344 MockRead data_reads1[] = {
5345 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:045346 // Negotiate and NTLM are often requested together. However, we only want
5347 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
5348 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:245349 MockRead("WWW-Authenticate: NTLM\r\n"),
5350 MockRead("Connection: close\r\n"),
5351 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365352 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245353 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065354 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:245355 };
5356
5357 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:225358 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:245359 // request we should be issuing -- the final header line contains a Type
5360 // 1 message.
5361 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5362 "Host: 172.22.68.17\r\n"
5363 "Connection: keep-alive\r\n"
5364 "Authorization: NTLM "
5365 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5366
5367 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5368 // (the credentials for the origin server). The second request continues
5369 // on the same connection.
5370 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5371 "Host: 172.22.68.17\r\n"
5372 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:295373 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5374 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5375 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
5376 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
5377 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245378 };
5379
5380 MockRead data_reads2[] = {
5381 // The origin server responds with a Type 2 message.
5382 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5383 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:295384 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:245385 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5386 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5387 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5388 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5389 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5390 "BtAAAAAAA=\r\n"),
5391 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365392 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245393 MockRead("You are not authorized to view this page\r\n"),
5394
5395 // Lastly we get the desired content.
5396 MockRead("HTTP/1.1 200 OK\r\n"),
5397 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
5398 MockRead("Content-Length: 13\r\n\r\n"),
5399 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:065400 MockRead(SYNCHRONOUS, OK),
[email protected]3f918782009-02-28 01:29:245401 };
5402
[email protected]31a2bfe2010-02-09 08:03:395403 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5404 data_writes1, arraysize(data_writes1));
5405 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5406 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:075407 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5408 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:245409
[email protected]49639fa2011-12-20 23:22:415410 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:245411
[email protected]262eec82013-03-19 21:01:365412 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505413 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505414
[email protected]49639fa2011-12-20 23:22:415415 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425416 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:245417
5418 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425419 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:245420
[email protected]0757e7702009-03-27 04:00:225421 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5422
[email protected]1c773ea12009-04-28 19:58:425423 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:045424 ASSERT_FALSE(response == NULL);
5425 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]3f918782009-02-28 01:29:245426
[email protected]49639fa2011-12-20 23:22:415427 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:255428
[email protected]f3cf9802011-10-28 18:44:585429 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:415430 callback2.callback());
[email protected]10af5fe72011-01-31 16:17:255431 EXPECT_EQ(ERR_IO_PENDING, rv);
5432
5433 rv = callback2.WaitForResult();
5434 EXPECT_EQ(OK, rv);
5435
5436 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5437
5438 response = trans->GetResponseInfo();
5439 ASSERT_TRUE(response != NULL);
[email protected]10af5fe72011-01-31 16:17:255440 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5441
[email protected]49639fa2011-12-20 23:22:415442 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:245443
[email protected]49639fa2011-12-20 23:22:415444 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425445 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:245446
[email protected]0757e7702009-03-27 04:00:225447 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425448 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:245449
5450 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505451 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:245452 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5453 EXPECT_EQ(13, response->headers->GetContentLength());
5454}
5455
[email protected]385a4672009-03-11 22:21:295456// Enter a wrong password, and then the correct one.
[email protected]23e482282013-06-14 16:08:025457TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:425458 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:295459 request.method = "GET";
5460 request.url = GURL("http://172.22.68.17/kids/login.aspx");
5461 request.load_flags = 0;
5462
[email protected]cb9bf6ca2011-01-28 13:15:275463 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
5464 MockGetHostName);
mmenkee65e7af2015-10-13 17:16:425465 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275466
[email protected]385a4672009-03-11 22:21:295467 MockWrite data_writes1[] = {
5468 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5469 "Host: 172.22.68.17\r\n"
5470 "Connection: keep-alive\r\n\r\n"),
5471 };
5472
5473 MockRead data_reads1[] = {
5474 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:045475 // Negotiate and NTLM are often requested together. However, we only want
5476 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
5477 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:295478 MockRead("WWW-Authenticate: NTLM\r\n"),
5479 MockRead("Connection: close\r\n"),
5480 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365481 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295482 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065483 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:295484 };
5485
5486 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:225487 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:295488 // request we should be issuing -- the final header line contains a Type
5489 // 1 message.
5490 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5491 "Host: 172.22.68.17\r\n"
5492 "Connection: keep-alive\r\n"
5493 "Authorization: NTLM "
5494 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5495
5496 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5497 // (the credentials for the origin server). The second request continues
5498 // on the same connection.
5499 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5500 "Host: 172.22.68.17\r\n"
5501 "Connection: keep-alive\r\n"
5502 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5503 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5504 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
5505 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
5506 "4Ww7b7E=\r\n\r\n"),
5507 };
5508
5509 MockRead data_reads2[] = {
5510 // The origin server responds with a Type 2 message.
5511 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5512 MockRead("WWW-Authenticate: NTLM "
5513 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
5514 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5515 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5516 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5517 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5518 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5519 "BtAAAAAAA=\r\n"),
5520 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365521 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295522 MockRead("You are not authorized to view this page\r\n"),
5523
5524 // Wrong password.
5525 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:295526 MockRead("WWW-Authenticate: NTLM\r\n"),
5527 MockRead("Connection: close\r\n"),
5528 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365529 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295530 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065531 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:295532 };
5533
5534 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:225535 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:295536 // request we should be issuing -- the final header line contains a Type
5537 // 1 message.
5538 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5539 "Host: 172.22.68.17\r\n"
5540 "Connection: keep-alive\r\n"
5541 "Authorization: NTLM "
5542 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5543
5544 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5545 // (the credentials for the origin server). The second request continues
5546 // on the same connection.
5547 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5548 "Host: 172.22.68.17\r\n"
5549 "Connection: keep-alive\r\n"
5550 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5551 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5552 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
5553 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
5554 "+4MUm7c=\r\n\r\n"),
5555 };
5556
5557 MockRead data_reads3[] = {
5558 // The origin server responds with a Type 2 message.
5559 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5560 MockRead("WWW-Authenticate: NTLM "
5561 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
5562 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5563 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5564 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5565 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5566 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5567 "BtAAAAAAA=\r\n"),
5568 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365569 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295570 MockRead("You are not authorized to view this page\r\n"),
5571
5572 // Lastly we get the desired content.
5573 MockRead("HTTP/1.1 200 OK\r\n"),
5574 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
5575 MockRead("Content-Length: 13\r\n\r\n"),
5576 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:065577 MockRead(SYNCHRONOUS, OK),
[email protected]385a4672009-03-11 22:21:295578 };
5579
[email protected]31a2bfe2010-02-09 08:03:395580 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5581 data_writes1, arraysize(data_writes1));
5582 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5583 data_writes2, arraysize(data_writes2));
5584 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5585 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:075586 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5587 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5588 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:295589
[email protected]49639fa2011-12-20 23:22:415590 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:295591
[email protected]262eec82013-03-19 21:01:365592 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505593 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505594
[email protected]49639fa2011-12-20 23:22:415595 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425596 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:295597
5598 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425599 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:295600
[email protected]0757e7702009-03-27 04:00:225601 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:295602
[email protected]1c773ea12009-04-28 19:58:425603 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505604 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045605 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]385a4672009-03-11 22:21:295606
[email protected]49639fa2011-12-20 23:22:415607 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:295608
[email protected]0757e7702009-03-27 04:00:225609 // Enter the wrong password.
[email protected]f3cf9802011-10-28 18:44:585610 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
[email protected]49639fa2011-12-20 23:22:415611 callback2.callback());
[email protected]1c773ea12009-04-28 19:58:425612 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:295613
[email protected]10af5fe72011-01-31 16:17:255614 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425615 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:295616
[email protected]0757e7702009-03-27 04:00:225617 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:415618 TestCompletionCallback callback3;
5619 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425620 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:255621 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425622 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:225623 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5624
5625 response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:045626 ASSERT_FALSE(response == NULL);
5627 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]0757e7702009-03-27 04:00:225628
[email protected]49639fa2011-12-20 23:22:415629 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:225630
5631 // Now enter the right password.
[email protected]f3cf9802011-10-28 18:44:585632 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:415633 callback4.callback());
[email protected]10af5fe72011-01-31 16:17:255634 EXPECT_EQ(ERR_IO_PENDING, rv);
5635
5636 rv = callback4.WaitForResult();
5637 EXPECT_EQ(OK, rv);
5638
5639 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5640
[email protected]49639fa2011-12-20 23:22:415641 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:255642
5643 // One more roundtrip
[email protected]49639fa2011-12-20 23:22:415644 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
[email protected]1c773ea12009-04-28 19:58:425645 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:225646
5647 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425648 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:225649
[email protected]385a4672009-03-11 22:21:295650 response = trans->GetResponseInfo();
5651 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5652 EXPECT_EQ(13, response->headers->GetContentLength());
5653}
[email protected]ea9dc9a2009-09-05 00:43:325654#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:295655
[email protected]4ddaf2502008-10-23 18:26:195656// Test reading a server response which has only headers, and no body.
5657// After some maximum number of bytes is consumed, the transaction should
5658// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
[email protected]23e482282013-06-14 16:08:025659TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:425660 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:195661 request.method = "GET";
bncce36dca22015-04-21 22:11:235662 request.url = GURL("http://www.example.org/");
[email protected]4ddaf2502008-10-23 18:26:195663 request.load_flags = 0;
5664
mmenkee65e7af2015-10-13 17:16:425665 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275666 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:415667 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:275668
[email protected]b75b7b2f2009-10-06 00:54:535669 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:435670 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:535671 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:195672
5673 MockRead data_reads[] = {
5674 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:065675 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:195676 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:065677 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:195678 };
[email protected]31a2bfe2010-02-09 08:03:395679 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:075680 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:195681
[email protected]49639fa2011-12-20 23:22:415682 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:195683
[email protected]49639fa2011-12-20 23:22:415684 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425685 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:195686
5687 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425688 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:195689}
[email protected]f4e426b2008-11-05 00:24:495690
5691// Make sure that we don't try to reuse a TCPClientSocket when failing to
5692// establish tunnel.
5693// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]23e482282013-06-14 16:08:025694TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:235695 DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:275696 HttpRequestInfo request;
5697 request.method = "GET";
bncce36dca22015-04-21 22:11:235698 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:275699 request.load_flags = 0;
5700
[email protected]f4e426b2008-11-05 00:24:495701 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035702 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]db8f44c2008-12-13 04:52:015703
mmenkee65e7af2015-10-13 17:16:425704 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:495705
[email protected]262eec82013-03-19 21:01:365706 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505707 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f4e426b2008-11-05 00:24:495708
[email protected]f4e426b2008-11-05 00:24:495709 // Since we have proxy, should try to establish tunnel.
5710 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175711 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5712 "Host: www.example.org:443\r\n"
5713 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:495714 };
5715
[email protected]77848d12008-11-14 00:00:225716 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:495717 // connection. Usually a proxy would return 501 (not implemented),
5718 // or 200 (tunnel established).
5719 MockRead data_reads1[] = {
5720 MockRead("HTTP/1.1 404 Not Found\r\n"),
5721 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065722 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:495723 };
5724
[email protected]31a2bfe2010-02-09 08:03:395725 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5726 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:075727 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:495728
[email protected]49639fa2011-12-20 23:22:415729 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:495730
[email protected]49639fa2011-12-20 23:22:415731 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425732 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:495733
5734 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425735 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:495736
[email protected]b4404c02009-04-10 16:38:525737 // Empty the current queue. This is necessary because idle sockets are
5738 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345739 base::MessageLoop::current()->RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:525740
[email protected]f4e426b2008-11-05 00:24:495741 // We now check to make sure the TCPClientSocket was not added back to
5742 // the pool.
[email protected]90499482013-06-01 00:39:505743 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:495744 trans.reset();
[email protected]2da659e2013-05-23 20:51:345745 base::MessageLoop::current()->RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:495746 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:505747 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:495748}
[email protected]372d34a2008-11-05 21:30:515749
[email protected]1b157c02009-04-21 01:55:405750// Make sure that we recycle a socket after reading all of the response body.
[email protected]23e482282013-06-14 16:08:025751TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:425752 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:405753 request.method = "GET";
bncce36dca22015-04-21 22:11:235754 request.url = GURL("http://www.example.org/");
[email protected]1b157c02009-04-21 01:55:405755 request.load_flags = 0;
5756
mmenkee65e7af2015-10-13 17:16:425757 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275758
[email protected]262eec82013-03-19 21:01:365759 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505760 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:275761
[email protected]1b157c02009-04-21 01:55:405762 MockRead data_reads[] = {
5763 // A part of the response body is received with the response headers.
5764 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5765 // The rest of the response body is received in two parts.
5766 MockRead("lo"),
5767 MockRead(" world"),
5768 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:065769 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:405770 };
5771
[email protected]31a2bfe2010-02-09 08:03:395772 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:075773 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:405774
[email protected]49639fa2011-12-20 23:22:415775 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:405776
[email protected]49639fa2011-12-20 23:22:415777 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425778 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:405779
5780 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425781 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:405782
[email protected]1c773ea12009-04-28 19:58:425783 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505784 ASSERT_TRUE(response != NULL);
[email protected]1b157c02009-04-21 01:55:405785
[email protected]90499482013-06-01 00:39:505786 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]1b157c02009-04-21 01:55:405787 std::string status_line = response->headers->GetStatusLine();
5788 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
5789
[email protected]90499482013-06-01 00:39:505790 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:405791
5792 std::string response_data;
5793 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:425794 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:405795 EXPECT_EQ("hello world", response_data);
5796
5797 // Empty the current queue. This is necessary because idle sockets are
5798 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345799 base::MessageLoop::current()->RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:405800
5801 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:505802 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:405803}
5804
[email protected]76a505b2010-08-25 06:23:005805// Make sure that we recycle a SSL socket after reading all of the response
5806// body.
[email protected]23e482282013-06-14 16:08:025807TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:005808 HttpRequestInfo request;
5809 request.method = "GET";
bncce36dca22015-04-21 22:11:235810 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:005811 request.load_flags = 0;
5812
5813 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:235814 MockWrite(
5815 "GET / HTTP/1.1\r\n"
5816 "Host: www.example.org\r\n"
5817 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:005818 };
5819
5820 MockRead data_reads[] = {
5821 MockRead("HTTP/1.1 200 OK\r\n"),
5822 MockRead("Content-Length: 11\r\n\r\n"),
5823 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:065824 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:005825 };
5826
[email protected]8ddf8322012-02-23 18:08:065827 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075828 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:005829
5830 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5831 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:075832 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:005833
[email protected]49639fa2011-12-20 23:22:415834 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:005835
mmenkee65e7af2015-10-13 17:16:425836 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:365837 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505838 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:005839
[email protected]49639fa2011-12-20 23:22:415840 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:005841
5842 EXPECT_EQ(ERR_IO_PENDING, rv);
5843 EXPECT_EQ(OK, callback.WaitForResult());
5844
5845 const HttpResponseInfo* response = trans->GetResponseInfo();
5846 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:505847 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:005848 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5849
[email protected]90499482013-06-01 00:39:505850 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:005851
5852 std::string response_data;
5853 rv = ReadTransaction(trans.get(), &response_data);
5854 EXPECT_EQ(OK, rv);
5855 EXPECT_EQ("hello world", response_data);
5856
5857 // Empty the current queue. This is necessary because idle sockets are
5858 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345859 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:005860
5861 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:505862 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:005863}
5864
5865// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5866// from the pool and make sure that we recover okay.
[email protected]23e482282013-06-14 16:08:025867TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:005868 HttpRequestInfo request;
5869 request.method = "GET";
bncce36dca22015-04-21 22:11:235870 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:005871 request.load_flags = 0;
5872
5873 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:235874 MockWrite(
5875 "GET / HTTP/1.1\r\n"
5876 "Host: www.example.org\r\n"
5877 "Connection: keep-alive\r\n\r\n"),
5878 MockWrite(
5879 "GET / HTTP/1.1\r\n"
5880 "Host: www.example.org\r\n"
5881 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:005882 };
5883
5884 MockRead data_reads[] = {
5885 MockRead("HTTP/1.1 200 OK\r\n"),
5886 MockRead("Content-Length: 11\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065887 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]76a505b2010-08-25 06:23:005888 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:065889 MockRead(ASYNC, 0, 0) // EOF
[email protected]76a505b2010-08-25 06:23:005890 };
5891
[email protected]8ddf8322012-02-23 18:08:065892 SSLSocketDataProvider ssl(ASYNC, OK);
5893 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075894 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5895 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:005896
5897 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5898 data_writes, arraysize(data_writes));
5899 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
5900 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:075901 session_deps_.socket_factory->AddSocketDataProvider(&data);
5902 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:005903
[email protected]49639fa2011-12-20 23:22:415904 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:005905
mmenkee65e7af2015-10-13 17:16:425906 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:365907 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505908 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:005909
[email protected]49639fa2011-12-20 23:22:415910 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:005911
5912 EXPECT_EQ(ERR_IO_PENDING, rv);
5913 EXPECT_EQ(OK, callback.WaitForResult());
5914
5915 const HttpResponseInfo* response = trans->GetResponseInfo();
5916 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:505917 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:005918 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5919
[email protected]90499482013-06-01 00:39:505920 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:005921
5922 std::string response_data;
5923 rv = ReadTransaction(trans.get(), &response_data);
5924 EXPECT_EQ(OK, rv);
5925 EXPECT_EQ("hello world", response_data);
5926
5927 // Empty the current queue. This is necessary because idle sockets are
5928 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345929 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:005930
5931 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:505932 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:005933
5934 // Now start the second transaction, which should reuse the previous socket.
5935
[email protected]90499482013-06-01 00:39:505936 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:005937
[email protected]49639fa2011-12-20 23:22:415938 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:005939
5940 EXPECT_EQ(ERR_IO_PENDING, rv);
5941 EXPECT_EQ(OK, callback.WaitForResult());
5942
5943 response = trans->GetResponseInfo();
5944 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:505945 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:005946 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5947
[email protected]90499482013-06-01 00:39:505948 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:005949
5950 rv = ReadTransaction(trans.get(), &response_data);
5951 EXPECT_EQ(OK, rv);
5952 EXPECT_EQ("hello world", response_data);
5953
5954 // Empty the current queue. This is necessary because idle sockets are
5955 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345956 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:005957
5958 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:505959 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:005960}
5961
[email protected]b4404c02009-04-10 16:38:525962// Make sure that we recycle a socket after a zero-length response.
5963// http://crbug.com/9880
[email protected]23e482282013-06-14 16:08:025964TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:425965 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:525966 request.method = "GET";
bncce36dca22015-04-21 22:11:235967 request.url = GURL(
5968 "http://www.example.org/csi?v=3&s=web&action=&"
5969 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5970 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5971 "rt=prt.2642,ol.2649,xjs.2951");
[email protected]b4404c02009-04-10 16:38:525972 request.load_flags = 0;
5973
mmenkee65e7af2015-10-13 17:16:425974 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275975
[email protected]262eec82013-03-19 21:01:365976 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505977 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:275978
[email protected]b4404c02009-04-10 16:38:525979 MockRead data_reads[] = {
5980 MockRead("HTTP/1.1 204 No Content\r\n"
5981 "Content-Length: 0\r\n"
5982 "Content-Type: text/html\r\n\r\n"),
5983 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:065984 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:525985 };
5986
[email protected]31a2bfe2010-02-09 08:03:395987 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:075988 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:525989
[email protected]49639fa2011-12-20 23:22:415990 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:525991
[email protected]49639fa2011-12-20 23:22:415992 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425993 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:525994
5995 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425996 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:525997
[email protected]1c773ea12009-04-28 19:58:425998 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505999 ASSERT_TRUE(response != NULL);
[email protected]b4404c02009-04-10 16:38:526000
[email protected]90499482013-06-01 00:39:506001 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]b4404c02009-04-10 16:38:526002 std::string status_line = response->headers->GetStatusLine();
6003 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
6004
[email protected]90499482013-06-01 00:39:506005 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:526006
6007 std::string response_data;
6008 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:426009 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:526010 EXPECT_EQ("", 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]b4404c02009-04-10 16:38:526015
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, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:526018}
6019
[email protected]23e482282013-06-14 16:08:026020TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
olli.raula6df48b2a2015-11-26 07:40:226021 std::vector<scoped_ptr<UploadElementReader>> element_readers;
6022 element_readers.push_back(
6023 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
6024 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:276025
[email protected]1c773ea12009-04-28 19:58:426026 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:516027 // Transaction 1: a GET request that succeeds. The socket is recycled
6028 // after use.
6029 request[0].method = "GET";
6030 request[0].url = GURL("http://www.google.com/");
6031 request[0].load_flags = 0;
6032 // Transaction 2: a POST request. Reuses the socket kept alive from
6033 // transaction 1. The first attempts fails when writing the POST data.
6034 // This causes the transaction to retry with a new socket. The second
6035 // attempt succeeds.
6036 request[1].method = "POST";
6037 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:276038 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:516039 request[1].load_flags = 0;
6040
mmenkee65e7af2015-10-13 17:16:426041 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:516042
6043 // The first socket is used for transaction 1 and the first attempt of
6044 // transaction 2.
6045
6046 // The response of transaction 1.
6047 MockRead data_reads1[] = {
6048 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
6049 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066050 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:516051 };
6052 // The mock write results of transaction 1 and the first attempt of
6053 // transaction 2.
6054 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:066055 MockWrite(SYNCHRONOUS, 64), // GET
6056 MockWrite(SYNCHRONOUS, 93), // POST
6057 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:516058 };
[email protected]31a2bfe2010-02-09 08:03:396059 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6060 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:516061
6062 // The second socket is used for the second attempt of transaction 2.
6063
6064 // The response of transaction 2.
6065 MockRead data_reads2[] = {
6066 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
6067 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:066068 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:516069 };
6070 // The mock write results of the second attempt of transaction 2.
6071 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:066072 MockWrite(SYNCHRONOUS, 93), // POST
6073 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:516074 };
[email protected]31a2bfe2010-02-09 08:03:396075 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6076 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:516077
[email protected]bb88e1d32013-05-03 23:11:076078 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6079 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:516080
thestig9d3bb0c2015-01-24 00:49:516081 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:516082 "hello world", "welcome"
6083 };
6084
6085 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:426086 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506087 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]372d34a2008-11-05 21:30:516088
[email protected]49639fa2011-12-20 23:22:416089 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:516090
[email protected]49639fa2011-12-20 23:22:416091 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426092 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:516093
6094 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426095 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:516096
[email protected]1c773ea12009-04-28 19:58:426097 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506098 ASSERT_TRUE(response != NULL);
[email protected]372d34a2008-11-05 21:30:516099
[email protected]90499482013-06-01 00:39:506100 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]372d34a2008-11-05 21:30:516101 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6102
6103 std::string response_data;
6104 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:426105 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:516106 EXPECT_EQ(kExpectedResponseData[i], response_data);
6107 }
6108}
[email protected]f9ee6b52008-11-08 06:46:236109
6110// Test the request-challenge-retry sequence for basic auth when there is
6111// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:166112// it fails the identity from the URL is used to answer the challenge.
[email protected]23e482282013-06-14 16:08:026113TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:426114 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236115 request.method = "GET";
bncce36dca22015-04-21 22:11:236116 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:416117 request.load_flags = LOAD_NORMAL;
[email protected]a97cca42009-08-14 01:00:296118
mmenkee65e7af2015-10-13 17:16:426119 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276120 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416121 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276122
[email protected]a97cca42009-08-14 01:00:296123 // The password contains an escaped character -- for this test to pass it
6124 // will need to be unescaped by HttpNetworkTransaction.
6125 EXPECT_EQ("b%40r", request.url.password());
6126
[email protected]f9ee6b52008-11-08 06:46:236127 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236128 MockWrite(
6129 "GET / HTTP/1.1\r\n"
6130 "Host: www.example.org\r\n"
6131 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236132 };
6133
6134 MockRead data_reads1[] = {
6135 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6136 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6137 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066138 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236139 };
6140
[email protected]2262e3a2012-05-22 16:08:166141 // After the challenge above, the transaction will be restarted using the
6142 // identity from the url (foo, b@r) to answer the challenge.
6143 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236144 MockWrite(
6145 "GET / HTTP/1.1\r\n"
6146 "Host: www.example.org\r\n"
6147 "Connection: keep-alive\r\n"
6148 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166149 };
6150
6151 MockRead data_reads2[] = {
6152 MockRead("HTTP/1.0 200 OK\r\n"),
6153 MockRead("Content-Length: 100\r\n\r\n"),
6154 MockRead(SYNCHRONOUS, OK),
6155 };
6156
[email protected]31a2bfe2010-02-09 08:03:396157 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6158 data_writes1, arraysize(data_writes1));
[email protected]2262e3a2012-05-22 16:08:166159 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6160 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076161 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6162 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236163
[email protected]49639fa2011-12-20 23:22:416164 TestCompletionCallback callback1;
[email protected]49639fa2011-12-20 23:22:416165 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426166 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236167 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426168 EXPECT_EQ(OK, rv);
[email protected]2262e3a2012-05-22 16:08:166169 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6170
6171 TestCompletionCallback callback2;
6172 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6173 EXPECT_EQ(ERR_IO_PENDING, rv);
6174 rv = callback2.WaitForResult();
6175 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226176 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6177
[email protected]2262e3a2012-05-22 16:08:166178 const HttpResponseInfo* response = trans->GetResponseInfo();
6179 ASSERT_TRUE(response != NULL);
6180
6181 // There is no challenge info, since the identity in URL worked.
6182 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6183
6184 EXPECT_EQ(100, response->headers->GetContentLength());
6185
6186 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:346187 base::MessageLoop::current()->RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:166188}
6189
6190// Test the request-challenge-retry sequence for basic auth when there is an
6191// incorrect identity in the URL. The identity from the URL should be used only
6192// once.
[email protected]23e482282013-06-14 16:08:026193TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:166194 HttpRequestInfo request;
6195 request.method = "GET";
6196 // Note: the URL has a username:password in it. The password "baz" is
6197 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:236198 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:166199
6200 request.load_flags = LOAD_NORMAL;
6201
mmenkee65e7af2015-10-13 17:16:426202 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2262e3a2012-05-22 16:08:166203 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416204 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2262e3a2012-05-22 16:08:166205
6206 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236207 MockWrite(
6208 "GET / HTTP/1.1\r\n"
6209 "Host: www.example.org\r\n"
6210 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166211 };
6212
6213 MockRead data_reads1[] = {
6214 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6215 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6216 MockRead("Content-Length: 10\r\n\r\n"),
6217 MockRead(SYNCHRONOUS, ERR_FAILED),
6218 };
6219
6220 // After the challenge above, the transaction will be restarted using the
6221 // identity from the url (foo, baz) to answer the challenge.
6222 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236223 MockWrite(
6224 "GET / HTTP/1.1\r\n"
6225 "Host: www.example.org\r\n"
6226 "Connection: keep-alive\r\n"
6227 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166228 };
6229
6230 MockRead data_reads2[] = {
6231 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6232 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6233 MockRead("Content-Length: 10\r\n\r\n"),
6234 MockRead(SYNCHRONOUS, ERR_FAILED),
6235 };
6236
6237 // After the challenge above, the transaction will be restarted using the
6238 // identity supplied by the user (foo, bar) to answer the challenge.
6239 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236240 MockWrite(
6241 "GET / HTTP/1.1\r\n"
6242 "Host: www.example.org\r\n"
6243 "Connection: keep-alive\r\n"
6244 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166245 };
6246
6247 MockRead data_reads3[] = {
6248 MockRead("HTTP/1.0 200 OK\r\n"),
6249 MockRead("Content-Length: 100\r\n\r\n"),
6250 MockRead(SYNCHRONOUS, OK),
6251 };
6252
6253 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6254 data_writes1, arraysize(data_writes1));
6255 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6256 data_writes2, arraysize(data_writes2));
6257 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6258 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:076259 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6260 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6261 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:166262
6263 TestCompletionCallback callback1;
6264
6265 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6266 EXPECT_EQ(ERR_IO_PENDING, rv);
6267
6268 rv = callback1.WaitForResult();
6269 EXPECT_EQ(OK, rv);
6270
6271 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6272 TestCompletionCallback callback2;
6273 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6274 EXPECT_EQ(ERR_IO_PENDING, rv);
6275 rv = callback2.WaitForResult();
6276 EXPECT_EQ(OK, rv);
6277 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6278
6279 const HttpResponseInfo* response = trans->GetResponseInfo();
6280 ASSERT_TRUE(response != NULL);
6281 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6282
6283 TestCompletionCallback callback3;
6284 rv = trans->RestartWithAuth(
6285 AuthCredentials(kFoo, kBar), callback3.callback());
6286 EXPECT_EQ(ERR_IO_PENDING, rv);
6287 rv = callback3.WaitForResult();
6288 EXPECT_EQ(OK, rv);
6289 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6290
6291 response = trans->GetResponseInfo();
6292 ASSERT_TRUE(response != NULL);
6293
6294 // There is no challenge info, since the identity worked.
6295 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6296
6297 EXPECT_EQ(100, response->headers->GetContentLength());
6298
[email protected]ea9dc9a2009-09-05 00:43:326299 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:346300 base::MessageLoop::current()->RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:326301}
6302
[email protected]2217aa22013-10-11 03:03:546303
6304// Test the request-challenge-retry sequence for basic auth when there is a
6305// correct identity in the URL, but its use is being suppressed. The identity
6306// from the URL should never be used.
6307TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
6308 HttpRequestInfo request;
6309 request.method = "GET";
bncce36dca22015-04-21 22:11:236310 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:546311 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
6312
mmenkee65e7af2015-10-13 17:16:426313 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2217aa22013-10-11 03:03:546314 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416315 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2217aa22013-10-11 03:03:546316
6317 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236318 MockWrite(
6319 "GET / HTTP/1.1\r\n"
6320 "Host: www.example.org\r\n"
6321 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:546322 };
6323
6324 MockRead data_reads1[] = {
6325 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6326 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6327 MockRead("Content-Length: 10\r\n\r\n"),
6328 MockRead(SYNCHRONOUS, ERR_FAILED),
6329 };
6330
6331 // After the challenge above, the transaction will be restarted using the
6332 // identity supplied by the user, not the one in the URL, to answer the
6333 // challenge.
6334 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236335 MockWrite(
6336 "GET / HTTP/1.1\r\n"
6337 "Host: www.example.org\r\n"
6338 "Connection: keep-alive\r\n"
6339 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:546340 };
6341
6342 MockRead data_reads3[] = {
6343 MockRead("HTTP/1.0 200 OK\r\n"),
6344 MockRead("Content-Length: 100\r\n\r\n"),
6345 MockRead(SYNCHRONOUS, OK),
6346 };
6347
6348 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6349 data_writes1, arraysize(data_writes1));
6350 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6351 data_writes3, arraysize(data_writes3));
6352 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6353 session_deps_.socket_factory->AddSocketDataProvider(&data3);
6354
6355 TestCompletionCallback callback1;
6356 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6357 EXPECT_EQ(ERR_IO_PENDING, rv);
6358 rv = callback1.WaitForResult();
6359 EXPECT_EQ(OK, rv);
6360 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6361
6362 const HttpResponseInfo* response = trans->GetResponseInfo();
6363 ASSERT_TRUE(response != NULL);
6364 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6365
6366 TestCompletionCallback callback3;
6367 rv = trans->RestartWithAuth(
6368 AuthCredentials(kFoo, kBar), callback3.callback());
6369 EXPECT_EQ(ERR_IO_PENDING, rv);
6370 rv = callback3.WaitForResult();
6371 EXPECT_EQ(OK, rv);
6372 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6373
6374 response = trans->GetResponseInfo();
6375 ASSERT_TRUE(response != NULL);
6376
6377 // There is no challenge info, since the identity worked.
6378 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6379 EXPECT_EQ(100, response->headers->GetContentLength());
6380
6381 // Empty the current queue.
6382 base::MessageLoop::current()->RunUntilIdle();
6383}
6384
[email protected]f9ee6b52008-11-08 06:46:236385// Test that previously tried username/passwords for a realm get re-used.
[email protected]23e482282013-06-14 16:08:026386TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
mmenkee65e7af2015-10-13 17:16:426387 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:236388
6389 // Transaction 1: authenticate (foo, bar) on MyRealm1
6390 {
[email protected]1c773ea12009-04-28 19:58:426391 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236392 request.method = "GET";
bncce36dca22015-04-21 22:11:236393 request.url = GURL("http://www.example.org/x/y/z");
[email protected]f9ee6b52008-11-08 06:46:236394 request.load_flags = 0;
6395
[email protected]262eec82013-03-19 21:01:366396 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506397 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276398
[email protected]f9ee6b52008-11-08 06:46:236399 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236400 MockWrite(
6401 "GET /x/y/z HTTP/1.1\r\n"
6402 "Host: www.example.org\r\n"
6403 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236404 };
6405
6406 MockRead data_reads1[] = {
6407 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6408 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6409 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066410 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236411 };
6412
6413 // Resend with authorization (username=foo, password=bar)
6414 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236415 MockWrite(
6416 "GET /x/y/z HTTP/1.1\r\n"
6417 "Host: www.example.org\r\n"
6418 "Connection: keep-alive\r\n"
6419 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236420 };
6421
6422 // Sever accepts the authorization.
6423 MockRead data_reads2[] = {
6424 MockRead("HTTP/1.0 200 OK\r\n"),
6425 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066426 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236427 };
6428
[email protected]31a2bfe2010-02-09 08:03:396429 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6430 data_writes1, arraysize(data_writes1));
6431 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6432 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076433 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6434 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236435
[email protected]49639fa2011-12-20 23:22:416436 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236437
[email protected]49639fa2011-12-20 23:22:416438 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426439 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236440
6441 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426442 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236443
[email protected]1c773ea12009-04-28 19:58:426444 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506445 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046446 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:236447
[email protected]49639fa2011-12-20 23:22:416448 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:236449
[email protected]49639fa2011-12-20 23:22:416450 rv = trans->RestartWithAuth(
6451 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426452 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236453
6454 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426455 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236456
6457 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506458 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236459 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6460 EXPECT_EQ(100, response->headers->GetContentLength());
6461 }
6462
6463 // ------------------------------------------------------------------------
6464
6465 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
6466 {
[email protected]1c773ea12009-04-28 19:58:426467 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236468 request.method = "GET";
6469 // Note that Transaction 1 was at /x/y/z, so this is in the same
6470 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:236471 request.url = GURL("http://www.example.org/x/y/a/b");
[email protected]f9ee6b52008-11-08 06:46:236472 request.load_flags = 0;
6473
[email protected]262eec82013-03-19 21:01:366474 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506475 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276476
[email protected]f9ee6b52008-11-08 06:46:236477 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236478 MockWrite(
6479 "GET /x/y/a/b HTTP/1.1\r\n"
6480 "Host: www.example.org\r\n"
6481 "Connection: keep-alive\r\n"
6482 // Send preemptive authorization for MyRealm1
6483 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236484 };
6485
6486 // The server didn't like the preemptive authorization, and
6487 // challenges us for a different realm (MyRealm2).
6488 MockRead data_reads1[] = {
6489 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6490 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
6491 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066492 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236493 };
6494
6495 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
6496 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236497 MockWrite(
6498 "GET /x/y/a/b HTTP/1.1\r\n"
6499 "Host: www.example.org\r\n"
6500 "Connection: keep-alive\r\n"
6501 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236502 };
6503
6504 // Sever accepts the authorization.
6505 MockRead data_reads2[] = {
6506 MockRead("HTTP/1.0 200 OK\r\n"),
6507 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066508 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236509 };
6510
[email protected]31a2bfe2010-02-09 08:03:396511 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6512 data_writes1, arraysize(data_writes1));
6513 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6514 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076515 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6516 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236517
[email protected]49639fa2011-12-20 23:22:416518 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236519
[email protected]49639fa2011-12-20 23:22:416520 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426521 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236522
6523 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426524 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236525
[email protected]1c773ea12009-04-28 19:58:426526 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506527 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046528 ASSERT_TRUE(response->auth_challenge.get());
6529 EXPECT_FALSE(response->auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:236530 EXPECT_EQ("www.example.org:80",
[email protected]79cb5c12011-09-12 13:12:046531 response->auth_challenge->challenger.ToString());
6532 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:196533 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:236534
[email protected]49639fa2011-12-20 23:22:416535 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:236536
[email protected]49639fa2011-12-20 23:22:416537 rv = trans->RestartWithAuth(
6538 AuthCredentials(kFoo2, kBar2), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426539 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236540
6541 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426542 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236543
6544 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506545 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236546 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6547 EXPECT_EQ(100, response->headers->GetContentLength());
6548 }
6549
6550 // ------------------------------------------------------------------------
6551
6552 // Transaction 3: Resend a request in MyRealm's protection space --
6553 // succeed with preemptive authorization.
6554 {
[email protected]1c773ea12009-04-28 19:58:426555 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236556 request.method = "GET";
bncce36dca22015-04-21 22:11:236557 request.url = GURL("http://www.example.org/x/y/z2");
[email protected]f9ee6b52008-11-08 06:46:236558 request.load_flags = 0;
6559
[email protected]262eec82013-03-19 21:01:366560 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506561 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276562
[email protected]f9ee6b52008-11-08 06:46:236563 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236564 MockWrite(
6565 "GET /x/y/z2 HTTP/1.1\r\n"
6566 "Host: www.example.org\r\n"
6567 "Connection: keep-alive\r\n"
6568 // The authorization for MyRealm1 gets sent preemptively
6569 // (since the url is in the same protection space)
6570 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236571 };
6572
6573 // Sever accepts the preemptive authorization
6574 MockRead data_reads1[] = {
6575 MockRead("HTTP/1.0 200 OK\r\n"),
6576 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066577 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236578 };
6579
[email protected]31a2bfe2010-02-09 08:03:396580 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6581 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:076582 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:236583
[email protected]49639fa2011-12-20 23:22:416584 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236585
[email protected]49639fa2011-12-20 23:22:416586 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426587 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236588
6589 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426590 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236591
[email protected]1c773ea12009-04-28 19:58:426592 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506593 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236594
6595 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6596 EXPECT_EQ(100, response->headers->GetContentLength());
6597 }
6598
6599 // ------------------------------------------------------------------------
6600
6601 // Transaction 4: request another URL in MyRealm (however the
6602 // url is not known to belong to the protection space, so no pre-auth).
6603 {
[email protected]1c773ea12009-04-28 19:58:426604 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236605 request.method = "GET";
bncce36dca22015-04-21 22:11:236606 request.url = GURL("http://www.example.org/x/1");
[email protected]f9ee6b52008-11-08 06:46:236607 request.load_flags = 0;
6608
[email protected]262eec82013-03-19 21:01:366609 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506610 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276611
[email protected]f9ee6b52008-11-08 06:46:236612 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236613 MockWrite(
6614 "GET /x/1 HTTP/1.1\r\n"
6615 "Host: www.example.org\r\n"
6616 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236617 };
6618
6619 MockRead data_reads1[] = {
6620 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6621 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6622 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066623 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236624 };
6625
6626 // Resend with authorization from MyRealm's cache.
6627 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236628 MockWrite(
6629 "GET /x/1 HTTP/1.1\r\n"
6630 "Host: www.example.org\r\n"
6631 "Connection: keep-alive\r\n"
6632 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236633 };
6634
6635 // Sever accepts the authorization.
6636 MockRead data_reads2[] = {
6637 MockRead("HTTP/1.0 200 OK\r\n"),
6638 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066639 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236640 };
6641
[email protected]31a2bfe2010-02-09 08:03:396642 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6643 data_writes1, arraysize(data_writes1));
6644 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6645 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076646 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6647 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236648
[email protected]49639fa2011-12-20 23:22:416649 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236650
[email protected]49639fa2011-12-20 23:22:416651 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426652 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236653
6654 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426655 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236656
[email protected]0757e7702009-03-27 04:00:226657 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:416658 TestCompletionCallback callback2;
6659 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426660 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:226661 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426662 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226663 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6664
[email protected]1c773ea12009-04-28 19:58:426665 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506666 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236667 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6668 EXPECT_EQ(100, response->headers->GetContentLength());
6669 }
6670
6671 // ------------------------------------------------------------------------
6672
6673 // Transaction 5: request a URL in MyRealm, but the server rejects the
6674 // cached identity. Should invalidate and re-prompt.
6675 {
[email protected]1c773ea12009-04-28 19:58:426676 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236677 request.method = "GET";
bncce36dca22015-04-21 22:11:236678 request.url = GURL("http://www.example.org/p/q/t");
[email protected]f9ee6b52008-11-08 06:46:236679 request.load_flags = 0;
6680
[email protected]262eec82013-03-19 21:01:366681 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506682 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276683
[email protected]f9ee6b52008-11-08 06:46:236684 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236685 MockWrite(
6686 "GET /p/q/t HTTP/1.1\r\n"
6687 "Host: www.example.org\r\n"
6688 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236689 };
6690
6691 MockRead data_reads1[] = {
6692 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6693 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6694 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066695 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236696 };
6697
6698 // Resend with authorization from cache for MyRealm.
6699 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236700 MockWrite(
6701 "GET /p/q/t HTTP/1.1\r\n"
6702 "Host: www.example.org\r\n"
6703 "Connection: keep-alive\r\n"
6704 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236705 };
6706
6707 // Sever rejects the authorization.
6708 MockRead data_reads2[] = {
6709 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6710 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6711 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066712 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236713 };
6714
6715 // At this point we should prompt for new credentials for MyRealm.
6716 // Restart with username=foo3, password=foo4.
6717 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236718 MockWrite(
6719 "GET /p/q/t HTTP/1.1\r\n"
6720 "Host: www.example.org\r\n"
6721 "Connection: keep-alive\r\n"
6722 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236723 };
6724
6725 // Sever accepts the authorization.
6726 MockRead data_reads3[] = {
6727 MockRead("HTTP/1.0 200 OK\r\n"),
6728 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066729 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236730 };
6731
[email protected]31a2bfe2010-02-09 08:03:396732 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6733 data_writes1, arraysize(data_writes1));
6734 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6735 data_writes2, arraysize(data_writes2));
6736 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6737 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:076738 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6739 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6740 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:236741
[email protected]49639fa2011-12-20 23:22:416742 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236743
[email protected]49639fa2011-12-20 23:22:416744 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426745 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236746
6747 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426748 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236749
[email protected]0757e7702009-03-27 04:00:226750 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:416751 TestCompletionCallback callback2;
6752 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426753 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:226754 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426755 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226756 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6757
[email protected]1c773ea12009-04-28 19:58:426758 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506759 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046760 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:236761
[email protected]49639fa2011-12-20 23:22:416762 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:236763
[email protected]49639fa2011-12-20 23:22:416764 rv = trans->RestartWithAuth(
6765 AuthCredentials(kFoo3, kBar3), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:426766 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236767
[email protected]0757e7702009-03-27 04:00:226768 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426769 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236770
6771 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506772 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236773 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6774 EXPECT_EQ(100, response->headers->GetContentLength());
6775 }
6776}
[email protected]89ceba9a2009-03-21 03:46:066777
[email protected]3c32c5f2010-05-18 15:18:126778// Tests that nonce count increments when multiple auth attempts
6779// are started with the same nonce.
[email protected]23e482282013-06-14 16:08:026780TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:446781 HttpAuthHandlerDigest::Factory* digest_factory =
6782 new HttpAuthHandlerDigest::Factory();
6783 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
6784 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6785 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:076786 session_deps_.http_auth_handler_factory.reset(digest_factory);
mmenkee65e7af2015-10-13 17:16:426787 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:126788
6789 // Transaction 1: authenticate (foo, bar) on MyRealm1
6790 {
[email protected]3c32c5f2010-05-18 15:18:126791 HttpRequestInfo request;
6792 request.method = "GET";
bncce36dca22015-04-21 22:11:236793 request.url = GURL("http://www.example.org/x/y/z");
[email protected]3c32c5f2010-05-18 15:18:126794 request.load_flags = 0;
6795
[email protected]262eec82013-03-19 21:01:366796 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506797 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276798
[email protected]3c32c5f2010-05-18 15:18:126799 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236800 MockWrite(
6801 "GET /x/y/z HTTP/1.1\r\n"
6802 "Host: www.example.org\r\n"
6803 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:126804 };
6805
6806 MockRead data_reads1[] = {
6807 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6808 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6809 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066810 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:126811 };
6812
6813 // Resend with authorization (username=foo, password=bar)
6814 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236815 MockWrite(
6816 "GET /x/y/z HTTP/1.1\r\n"
6817 "Host: www.example.org\r\n"
6818 "Connection: keep-alive\r\n"
6819 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6820 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6821 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6822 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:126823 };
6824
6825 // Sever accepts the authorization.
6826 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:086827 MockRead("HTTP/1.0 200 OK\r\n"),
6828 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:126829 };
6830
6831 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6832 data_writes1, arraysize(data_writes1));
6833 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6834 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076835 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6836 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:126837
[email protected]49639fa2011-12-20 23:22:416838 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:126839
[email protected]49639fa2011-12-20 23:22:416840 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:126841 EXPECT_EQ(ERR_IO_PENDING, rv);
6842
6843 rv = callback1.WaitForResult();
6844 EXPECT_EQ(OK, rv);
6845
6846 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506847 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046848 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
[email protected]3c32c5f2010-05-18 15:18:126849
[email protected]49639fa2011-12-20 23:22:416850 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:126851
[email protected]49639fa2011-12-20 23:22:416852 rv = trans->RestartWithAuth(
6853 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]3c32c5f2010-05-18 15:18:126854 EXPECT_EQ(ERR_IO_PENDING, rv);
6855
6856 rv = callback2.WaitForResult();
6857 EXPECT_EQ(OK, rv);
6858
6859 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506860 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:126861 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6862 }
6863
6864 // ------------------------------------------------------------------------
6865
6866 // Transaction 2: Request another resource in digestive's protection space.
6867 // This will preemptively add an Authorization header which should have an
6868 // "nc" value of 2 (as compared to 1 in the first use.
6869 {
[email protected]3c32c5f2010-05-18 15:18:126870 HttpRequestInfo request;
6871 request.method = "GET";
6872 // Note that Transaction 1 was at /x/y/z, so this is in the same
6873 // protection space as digest.
bncce36dca22015-04-21 22:11:236874 request.url = GURL("http://www.example.org/x/y/a/b");
[email protected]3c32c5f2010-05-18 15:18:126875 request.load_flags = 0;
6876
[email protected]262eec82013-03-19 21:01:366877 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506878 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276879
[email protected]3c32c5f2010-05-18 15:18:126880 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236881 MockWrite(
6882 "GET /x/y/a/b HTTP/1.1\r\n"
6883 "Host: www.example.org\r\n"
6884 "Connection: keep-alive\r\n"
6885 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6886 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6887 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6888 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:126889 };
6890
6891 // Sever accepts the authorization.
6892 MockRead data_reads1[] = {
6893 MockRead("HTTP/1.0 200 OK\r\n"),
6894 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066895 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:126896 };
6897
6898 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6899 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:076900 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:126901
[email protected]49639fa2011-12-20 23:22:416902 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:126903
[email protected]49639fa2011-12-20 23:22:416904 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:126905 EXPECT_EQ(ERR_IO_PENDING, rv);
6906
6907 rv = callback1.WaitForResult();
6908 EXPECT_EQ(OK, rv);
6909
6910 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506911 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:126912 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6913 }
6914}
6915
[email protected]89ceba9a2009-03-21 03:46:066916// Test the ResetStateForRestart() private method.
[email protected]23e482282013-06-14 16:08:026917TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:066918 // Create a transaction (the dependencies aren't important).
mmenkee65e7af2015-10-13 17:16:426919 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:406920 scoped_ptr<HttpNetworkTransaction> trans(
dcheng48459ac22014-08-26 00:46:416921 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]89ceba9a2009-03-21 03:46:066922
6923 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:066924 trans->read_buf_ = new IOBuffer(15);
6925 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:206926 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:066927
6928 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:146929 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:576930 response->auth_challenge = new AuthChallengeInfo();
[email protected]70d66502011-09-23 00:55:086931 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:576932 response->response_time = base::Time::Now();
6933 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:066934
6935 { // Setup state for response_.vary_data
6936 HttpRequestInfo request;
6937 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6938 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:276939 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:436940 request.extra_headers.SetHeader("Foo", "1");
6941 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:506942 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:066943 }
6944
6945 // Cause the above state to be reset.
6946 trans->ResetStateForRestart();
6947
6948 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:076949 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:066950 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:206951 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:576952 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6953 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:046954 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:086955 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:576956 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:066957}
6958
[email protected]bacff652009-03-31 17:50:336959// Test HTTPS connections to a site with a bad certificate
[email protected]23e482282013-06-14 16:08:026960TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:336961 HttpRequestInfo request;
6962 request.method = "GET";
bncce36dca22015-04-21 22:11:236963 request.url = GURL("https://www.example.org/");
[email protected]bacff652009-03-31 17:50:336964 request.load_flags = 0;
6965
mmenkee65e7af2015-10-13 17:16:426966 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276967 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416968 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276969
[email protected]bacff652009-03-31 17:50:336970 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:236971 MockWrite(
6972 "GET / HTTP/1.1\r\n"
6973 "Host: www.example.org\r\n"
6974 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:336975 };
6976
6977 MockRead data_reads[] = {
6978 MockRead("HTTP/1.0 200 OK\r\n"),
6979 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6980 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066981 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:336982 };
6983
[email protected]5ecc992a42009-11-11 01:41:596984 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:396985 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6986 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:066987 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6988 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:336989
[email protected]bb88e1d32013-05-03 23:11:076990 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6991 session_deps_.socket_factory->AddSocketDataProvider(&data);
6992 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6993 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:336994
[email protected]49639fa2011-12-20 23:22:416995 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:336996
[email protected]49639fa2011-12-20 23:22:416997 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:336998 EXPECT_EQ(ERR_IO_PENDING, rv);
6999
7000 rv = callback.WaitForResult();
7001 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7002
[email protected]49639fa2011-12-20 23:22:417003 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:337004 EXPECT_EQ(ERR_IO_PENDING, rv);
7005
7006 rv = callback.WaitForResult();
7007 EXPECT_EQ(OK, rv);
7008
7009 const HttpResponseInfo* response = trans->GetResponseInfo();
7010
[email protected]fe2255a2011-09-20 19:37:507011 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:337012 EXPECT_EQ(100, response->headers->GetContentLength());
7013}
7014
7015// Test HTTPS connections to a site with a bad certificate, going through a
7016// proxy
[email protected]23e482282013-06-14 16:08:027017TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
rdsmith82957ad2015-09-16 19:42:037018 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]bacff652009-03-31 17:50:337019
7020 HttpRequestInfo request;
7021 request.method = "GET";
bncce36dca22015-04-21 22:11:237022 request.url = GURL("https://www.example.org/");
[email protected]bacff652009-03-31 17:50:337023 request.load_flags = 0;
7024
7025 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:177026 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7027 "Host: www.example.org:443\r\n"
7028 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337029 };
7030
7031 MockRead proxy_reads[] = {
7032 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067033 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:337034 };
7035
7036 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177037 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7038 "Host: www.example.org:443\r\n"
7039 "Proxy-Connection: keep-alive\r\n\r\n"),
7040 MockWrite("GET / HTTP/1.1\r\n"
7041 "Host: www.example.org\r\n"
7042 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337043 };
7044
7045 MockRead data_reads[] = {
7046 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7047 MockRead("HTTP/1.0 200 OK\r\n"),
7048 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7049 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067050 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:337051 };
7052
[email protected]31a2bfe2010-02-09 08:03:397053 StaticSocketDataProvider ssl_bad_certificate(
7054 proxy_reads, arraysize(proxy_reads),
7055 proxy_writes, arraysize(proxy_writes));
7056 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7057 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067058 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7059 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:337060
[email protected]bb88e1d32013-05-03 23:11:077061 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7062 session_deps_.socket_factory->AddSocketDataProvider(&data);
7063 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7064 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:337065
[email protected]49639fa2011-12-20 23:22:417066 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:337067
7068 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:077069 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:337070
mmenkee65e7af2015-10-13 17:16:427071 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:407072 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417073 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bacff652009-03-31 17:50:337074
[email protected]49639fa2011-12-20 23:22:417075 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:337076 EXPECT_EQ(ERR_IO_PENDING, rv);
7077
7078 rv = callback.WaitForResult();
7079 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7080
[email protected]49639fa2011-12-20 23:22:417081 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:337082 EXPECT_EQ(ERR_IO_PENDING, rv);
7083
7084 rv = callback.WaitForResult();
7085 EXPECT_EQ(OK, rv);
7086
7087 const HttpResponseInfo* response = trans->GetResponseInfo();
7088
[email protected]fe2255a2011-09-20 19:37:507089 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:337090 EXPECT_EQ(100, response->headers->GetContentLength());
7091 }
7092}
7093
[email protected]2df19bb2010-08-25 20:13:467094
7095// Test HTTPS connections to a site, going through an HTTPS proxy
[email protected]23e482282013-06-14 16:08:027096TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037097 session_deps_.proxy_service =
7098 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:517099 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:077100 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:467101
7102 HttpRequestInfo request;
7103 request.method = "GET";
bncce36dca22015-04-21 22:11:237104 request.url = GURL("https://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467105 request.load_flags = 0;
7106
7107 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177108 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7109 "Host: www.example.org:443\r\n"
7110 "Proxy-Connection: keep-alive\r\n\r\n"),
7111 MockWrite("GET / HTTP/1.1\r\n"
7112 "Host: www.example.org\r\n"
7113 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467114 };
7115
7116 MockRead data_reads[] = {
7117 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7118 MockRead("HTTP/1.1 200 OK\r\n"),
7119 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7120 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067121 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467122 };
7123
7124 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7125 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067126 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
7127 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:467128
[email protected]bb88e1d32013-05-03 23:11:077129 session_deps_.socket_factory->AddSocketDataProvider(&data);
7130 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
7131 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:467132
[email protected]49639fa2011-12-20 23:22:417133 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:467134
mmenkee65e7af2015-10-13 17:16:427135 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:467136 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417137 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2df19bb2010-08-25 20:13:467138
[email protected]49639fa2011-12-20 23:22:417139 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:467140 EXPECT_EQ(ERR_IO_PENDING, rv);
7141
7142 rv = callback.WaitForResult();
7143 EXPECT_EQ(OK, rv);
7144 const HttpResponseInfo* response = trans->GetResponseInfo();
7145
[email protected]fe2255a2011-09-20 19:37:507146 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:467147
7148 EXPECT_TRUE(response->headers->IsKeepAlive());
7149 EXPECT_EQ(200, response->headers->response_code());
7150 EXPECT_EQ(100, response->headers->GetContentLength());
7151 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:207152
7153 LoadTimingInfo load_timing_info;
7154 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7155 TestLoadTimingNotReusedWithPac(load_timing_info,
7156 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:467157}
7158
[email protected]511f6f52010-12-17 03:58:297159// Test an HTTPS Proxy's ability to redirect a CONNECT request
[email protected]23e482282013-06-14 16:08:027160TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037161 session_deps_.proxy_service =
7162 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:517163 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:077164 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:297165
7166 HttpRequestInfo request;
7167 request.method = "GET";
bncce36dca22015-04-21 22:11:237168 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297169 request.load_flags = 0;
7170
7171 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177172 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7173 "Host: www.example.org:443\r\n"
7174 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:297175 };
7176
7177 MockRead data_reads[] = {
7178 MockRead("HTTP/1.1 302 Redirect\r\n"),
7179 MockRead("Location: http://login.example.com/\r\n"),
7180 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067181 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:297182 };
7183
7184 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7185 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067186 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:297187
[email protected]bb88e1d32013-05-03 23:11:077188 session_deps_.socket_factory->AddSocketDataProvider(&data);
7189 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297190
[email protected]49639fa2011-12-20 23:22:417191 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297192
mmenkee65e7af2015-10-13 17:16:427193 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297194 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417195 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297196
[email protected]49639fa2011-12-20 23:22:417197 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297198 EXPECT_EQ(ERR_IO_PENDING, rv);
7199
7200 rv = callback.WaitForResult();
7201 EXPECT_EQ(OK, rv);
7202 const HttpResponseInfo* response = trans->GetResponseInfo();
7203
[email protected]fe2255a2011-09-20 19:37:507204 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:297205
7206 EXPECT_EQ(302, response->headers->response_code());
7207 std::string url;
7208 EXPECT_TRUE(response->headers->IsRedirect(&url));
7209 EXPECT_EQ("http://login.example.com/", url);
[email protected]029c83b62013-01-24 05:28:207210
7211 // In the case of redirects from proxies, HttpNetworkTransaction returns
7212 // timing for the proxy connection instead of the connection to the host,
7213 // and no send / receive times.
7214 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
7215 LoadTimingInfo load_timing_info;
7216 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7217
7218 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:297219 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:207220
7221 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
7222 EXPECT_LE(load_timing_info.proxy_resolve_start,
7223 load_timing_info.proxy_resolve_end);
7224 EXPECT_LE(load_timing_info.proxy_resolve_end,
7225 load_timing_info.connect_timing.connect_start);
7226 ExpectConnectTimingHasTimes(
7227 load_timing_info.connect_timing,
7228 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
7229
7230 EXPECT_TRUE(load_timing_info.send_start.is_null());
7231 EXPECT_TRUE(load_timing_info.send_end.is_null());
7232 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]511f6f52010-12-17 03:58:297233}
7234
7235// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
[email protected]23e482282013-06-14 16:08:027236TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
rdsmith82957ad2015-09-16 19:42:037237 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297238
7239 HttpRequestInfo request;
7240 request.method = "GET";
bncce36dca22015-04-21 22:11:237241 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297242 request.load_flags = 0;
7243
lgarrona91df87f2014-12-05 00:51:347244 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237245 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207246 scoped_ptr<SpdyFrame> goaway(
7247 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]511f6f52010-12-17 03:58:297248 MockWrite data_writes[] = {
rch8e6c6c42015-05-01 14:05:137249 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
7250 CreateMockWrite(*goaway.get(), 2, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:297251 };
7252
7253 static const char* const kExtraHeaders[] = {
7254 "location",
7255 "http://login.example.com/",
7256 };
[email protected]ff98d7f02012-03-22 21:44:197257 scoped_ptr<SpdyFrame> resp(
[email protected]23e482282013-06-14 16:08:027258 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
[email protected]511f6f52010-12-17 03:58:297259 arraysize(kExtraHeaders)/2, 1));
7260 MockRead data_reads[] = {
rch8e6c6c42015-05-01 14:05:137261 CreateMockRead(*resp.get(), 1), MockRead(ASYNC, 0, 3), // EOF
[email protected]511f6f52010-12-17 03:58:297262 };
7263
rch8e6c6c42015-05-01 14:05:137264 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
7265 arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067266 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
rdsmithebb50aa2015-11-12 03:44:387267 proxy_ssl.SetNextProto(GetProtocol());
[email protected]511f6f52010-12-17 03:58:297268
[email protected]bb88e1d32013-05-03 23:11:077269 session_deps_.socket_factory->AddSocketDataProvider(&data);
7270 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297271
[email protected]49639fa2011-12-20 23:22:417272 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297273
mmenkee65e7af2015-10-13 17:16:427274 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297275 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417276 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297277
[email protected]49639fa2011-12-20 23:22:417278 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297279 EXPECT_EQ(ERR_IO_PENDING, rv);
7280
7281 rv = callback.WaitForResult();
7282 EXPECT_EQ(OK, rv);
7283 const HttpResponseInfo* response = trans->GetResponseInfo();
7284
[email protected]fe2255a2011-09-20 19:37:507285 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:297286
7287 EXPECT_EQ(302, response->headers->response_code());
7288 std::string url;
7289 EXPECT_TRUE(response->headers->IsRedirect(&url));
7290 EXPECT_EQ("http://login.example.com/", url);
7291}
7292
[email protected]4eddbc732012-08-09 05:40:177293// Test that an HTTPS proxy's response to a CONNECT request is filtered.
[email protected]23e482282013-06-14 16:08:027294TEST_P(HttpNetworkTransactionTest,
[email protected]4eddbc732012-08-09 05:40:177295 ErrorResponseToHttpsConnectViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037296 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297297
7298 HttpRequestInfo request;
7299 request.method = "GET";
bncce36dca22015-04-21 22:11:237300 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297301 request.load_flags = 0;
7302
7303 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177304 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7305 "Host: www.example.org:443\r\n"
7306 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:297307 };
7308
7309 MockRead data_reads[] = {
7310 MockRead("HTTP/1.1 404 Not Found\r\n"),
7311 MockRead("Content-Length: 23\r\n\r\n"),
7312 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:067313 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:297314 };
7315
7316 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7317 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067318 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:297319
[email protected]bb88e1d32013-05-03 23:11:077320 session_deps_.socket_factory->AddSocketDataProvider(&data);
7321 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297322
[email protected]49639fa2011-12-20 23:22:417323 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297324
mmenkee65e7af2015-10-13 17:16:427325 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297326 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417327 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297328
[email protected]49639fa2011-12-20 23:22:417329 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297330 EXPECT_EQ(ERR_IO_PENDING, rv);
7331
7332 rv = callback.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:177333 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]511f6f52010-12-17 03:58:297334
[email protected]4eddbc732012-08-09 05:40:177335 // TODO(ttuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:297336}
7337
[email protected]4eddbc732012-08-09 05:40:177338// Test that a SPDY proxy's response to a CONNECT request is filtered.
[email protected]23e482282013-06-14 16:08:027339TEST_P(HttpNetworkTransactionTest,
[email protected]4eddbc732012-08-09 05:40:177340 ErrorResponseToHttpsConnectViaSpdyProxy) {
rdsmith82957ad2015-09-16 19:42:037341 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297342
7343 HttpRequestInfo request;
7344 request.method = "GET";
bncce36dca22015-04-21 22:11:237345 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297346 request.load_flags = 0;
7347
lgarrona91df87f2014-12-05 00:51:347348 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237349 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207350 scoped_ptr<SpdyFrame> rst(
7351 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]511f6f52010-12-17 03:58:297352 MockWrite data_writes[] = {
rch8e6c6c42015-05-01 14:05:137353 CreateMockWrite(*conn.get(), 0), CreateMockWrite(*rst.get(), 3),
[email protected]511f6f52010-12-17 03:58:297354 };
7355
7356 static const char* const kExtraHeaders[] = {
7357 "location",
7358 "http://login.example.com/",
7359 };
[email protected]ff98d7f02012-03-22 21:44:197360 scoped_ptr<SpdyFrame> resp(
[email protected]23e482282013-06-14 16:08:027361 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
[email protected]511f6f52010-12-17 03:58:297362 arraysize(kExtraHeaders)/2, 1));
[email protected]ff98d7f02012-03-22 21:44:197363 scoped_ptr<SpdyFrame> body(
[email protected]23e482282013-06-14 16:08:027364 spdy_util_.ConstructSpdyBodyFrame(
7365 1, "The host does not exist", 23, true));
[email protected]511f6f52010-12-17 03:58:297366 MockRead data_reads[] = {
rch8e6c6c42015-05-01 14:05:137367 CreateMockRead(*resp.get(), 1),
7368 CreateMockRead(*body.get(), 2),
7369 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:297370 };
7371
rch8e6c6c42015-05-01 14:05:137372 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
7373 arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067374 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
rdsmithebb50aa2015-11-12 03:44:387375 proxy_ssl.SetNextProto(GetProtocol());
[email protected]511f6f52010-12-17 03:58:297376
[email protected]bb88e1d32013-05-03 23:11:077377 session_deps_.socket_factory->AddSocketDataProvider(&data);
7378 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297379
[email protected]49639fa2011-12-20 23:22:417380 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297381
mmenkee65e7af2015-10-13 17:16:427382 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297383 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417384 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297385
[email protected]49639fa2011-12-20 23:22:417386 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297387 EXPECT_EQ(ERR_IO_PENDING, rv);
7388
7389 rv = callback.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:177390 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]511f6f52010-12-17 03:58:297391
[email protected]4eddbc732012-08-09 05:40:177392 // TODO(ttuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:297393}
7394
[email protected]0c5fb722012-02-28 11:50:357395// Test the request-challenge-retry sequence for basic auth, through
7396// a SPDY proxy over a single SPDY session.
[email protected]23e482282013-06-14 16:08:027397TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:357398 HttpRequestInfo request;
7399 request.method = "GET";
bncce36dca22015-04-21 22:11:237400 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:357401 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:297402 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]0c5fb722012-02-28 11:50:357403
7404 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037405 session_deps_.proxy_service =
7406 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
vishal.b62985ca92015-04-17 08:45:517407 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077408 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:427409 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:357410
7411 // Since we have proxy, should try to establish tunnel.
lgarrona91df87f2014-12-05 00:51:347412 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237413 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207414 scoped_ptr<SpdyFrame> rst(
7415 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
rdsmithebb50aa2015-11-12 03:44:387416 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:357417
7418 // After calling trans->RestartWithAuth(), this is the request we should
7419 // be issuing -- the final header line contains the credentials.
7420 const char* const kAuthCredentials[] = {
7421 "proxy-authorization", "Basic Zm9vOmJhcg==",
7422 };
[email protected]fba2dbde2013-05-24 16:09:017423 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
lgarrona91df87f2014-12-05 00:51:347424 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
bncce36dca22015-04-21 22:11:237425 HostPortPair("www.example.org", 443)));
7426 // fetch https://www.example.org/ via HTTP
7427 const char get[] =
7428 "GET / HTTP/1.1\r\n"
7429 "Host: www.example.org\r\n"
7430 "Connection: keep-alive\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:197431 scoped_ptr<SpdyFrame> wrapped_get(
[email protected]23e482282013-06-14 16:08:027432 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
[email protected]0c5fb722012-02-28 11:50:357433
7434 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137435 CreateMockWrite(*req, 0, ASYNC),
7436 CreateMockWrite(*rst, 2, ASYNC),
7437 CreateMockWrite(*connect2, 3),
7438 CreateMockWrite(*wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:357439 };
7440
7441 // The proxy responds to the connect with a 407, using a persistent
7442 // connection.
thestig9d3bb0c2015-01-24 00:49:517443 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:357444 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:357445 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
7446 };
[email protected]745aa9c2014-06-27 02:21:297447 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
7448 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:357449
[email protected]23e482282013-06-14 16:08:027450 scoped_ptr<SpdyFrame> conn_resp(
7451 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]0c5fb722012-02-28 11:50:357452 const char resp[] = "HTTP/1.1 200 OK\r\n"
7453 "Content-Length: 5\r\n\r\n";
7454
[email protected]ff98d7f02012-03-22 21:44:197455 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:027456 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
[email protected]ff98d7f02012-03-22 21:44:197457 scoped_ptr<SpdyFrame> wrapped_body(
[email protected]23e482282013-06-14 16:08:027458 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
[email protected]0c5fb722012-02-28 11:50:357459 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137460 CreateMockRead(*conn_auth_resp, 1, ASYNC),
7461 CreateMockRead(*conn_resp, 4, ASYNC),
7462 CreateMockRead(*wrapped_get_resp, 6, ASYNC),
7463 CreateMockRead(*wrapped_body, 7, ASYNC),
7464 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:357465 };
7466
rch8e6c6c42015-05-01 14:05:137467 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7468 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077469 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:357470 // Negotiate SPDY to the proxy
7471 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387472 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077473 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:357474 // Vanilla SSL to the server
7475 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077476 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:357477
7478 TestCompletionCallback callback1;
7479
[email protected]262eec82013-03-19 21:01:367480 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507481 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0c5fb722012-02-28 11:50:357482
7483 int rv = trans->Start(&request, callback1.callback(), log.bound());
7484 EXPECT_EQ(ERR_IO_PENDING, rv);
7485
7486 rv = callback1.WaitForResult();
7487 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:467488 TestNetLogEntry::List entries;
[email protected]0c5fb722012-02-28 11:50:357489 log.GetEntries(&entries);
7490 size_t pos = ExpectLogContainsSomewhere(
7491 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7492 NetLog::PHASE_NONE);
7493 ExpectLogContainsSomewhere(
7494 entries, pos,
7495 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7496 NetLog::PHASE_NONE);
7497
7498 const HttpResponseInfo* response = trans->GetResponseInfo();
7499 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:507500 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]0c5fb722012-02-28 11:50:357501 EXPECT_EQ(407, response->headers->response_code());
7502 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7503 EXPECT_TRUE(response->auth_challenge.get() != NULL);
7504 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
7505
7506 TestCompletionCallback callback2;
7507
7508 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
7509 callback2.callback());
7510 EXPECT_EQ(ERR_IO_PENDING, rv);
7511
7512 rv = callback2.WaitForResult();
7513 EXPECT_EQ(OK, rv);
7514
7515 response = trans->GetResponseInfo();
7516 ASSERT_TRUE(response != NULL);
7517
7518 EXPECT_TRUE(response->headers->IsKeepAlive());
7519 EXPECT_EQ(200, response->headers->response_code());
7520 EXPECT_EQ(5, response->headers->GetContentLength());
7521 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7522
7523 // The password prompt info should not be set.
7524 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7525
[email protected]029c83b62013-01-24 05:28:207526 LoadTimingInfo load_timing_info;
7527 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7528 TestLoadTimingNotReusedWithPac(load_timing_info,
7529 CONNECT_TIMING_HAS_SSL_TIMES);
7530
[email protected]0c5fb722012-02-28 11:50:357531 trans.reset();
7532 session->CloseAllConnections();
7533}
7534
[email protected]7c6f7ba2012-04-03 04:09:297535// Test that an explicitly trusted SPDY proxy can push a resource from an
7536// origin that is different from that of its associated resource.
[email protected]23e482282013-06-14 16:08:027537TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
[email protected]7c6f7ba2012-04-03 04:09:297538 HttpRequestInfo request;
7539 HttpRequestInfo push_request;
7540
[email protected]7c6f7ba2012-04-03 04:09:297541 request.method = "GET";
bncce36dca22015-04-21 22:11:237542 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:297543 push_request.method = "GET";
7544 push_request.url = GURL("http://www.another-origin.com/foo.dat");
7545
[email protected]7c6f7ba2012-04-03 04:09:297546 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037547 session_deps_.proxy_service =
7548 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
vishal.b62985ca92015-04-17 08:45:517549 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077550 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:507551
7552 // Enable cross-origin push.
[email protected]bb88e1d32013-05-03 23:11:077553 session_deps_.trusted_spdy_proxy = "myproxy:70";
[email protected]61b4efc2012-04-27 18:12:507554
mmenkee65e7af2015-10-13 17:16:427555 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:297556
[email protected]cdf8f7e72013-05-23 10:56:467557 scoped_ptr<SpdyFrame> stream1_syn(
7558 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
[email protected]7c6f7ba2012-04-03 04:09:297559
7560 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137561 CreateMockWrite(*stream1_syn, 0, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:297562 };
7563
7564 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027565 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:297566
7567 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027568 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:297569
7570 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027571 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]7c6f7ba2012-04-03 04:09:297572 0,
7573 2,
7574 1,
7575 "http://www.another-origin.com/foo.dat"));
[email protected]8a0fc822013-06-27 20:52:437576 const char kPushedData[] = "pushed";
7577 scoped_ptr<SpdyFrame> stream2_body(
7578 spdy_util_.ConstructSpdyBodyFrame(
7579 2, kPushedData, strlen(kPushedData), true));
[email protected]7c6f7ba2012-04-03 04:09:297580
7581 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137582 CreateMockRead(*stream1_reply, 1, ASYNC),
7583 CreateMockRead(*stream2_syn, 2, ASYNC),
7584 CreateMockRead(*stream1_body, 3, ASYNC),
7585 CreateMockRead(*stream2_body, 4, ASYNC),
7586 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
[email protected]7c6f7ba2012-04-03 04:09:297587 };
7588
rch8e6c6c42015-05-01 14:05:137589 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7590 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077591 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:297592 // Negotiate SPDY to the proxy
7593 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387594 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077595 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:297596
[email protected]262eec82013-03-19 21:01:367597 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507598 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7c6f7ba2012-04-03 04:09:297599 TestCompletionCallback callback;
7600 int rv = trans->Start(&request, callback.callback(), log.bound());
7601 EXPECT_EQ(ERR_IO_PENDING, rv);
7602
7603 rv = callback.WaitForResult();
7604 EXPECT_EQ(OK, rv);
7605 const HttpResponseInfo* response = trans->GetResponseInfo();
7606
[email protected]262eec82013-03-19 21:01:367607 scoped_ptr<HttpTransaction> push_trans(
[email protected]90499482013-06-01 00:39:507608 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7609 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
[email protected]7c6f7ba2012-04-03 04:09:297610 EXPECT_EQ(ERR_IO_PENDING, rv);
7611
7612 rv = callback.WaitForResult();
7613 EXPECT_EQ(OK, rv);
7614 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
7615
7616 ASSERT_TRUE(response != NULL);
7617 EXPECT_TRUE(response->headers->IsKeepAlive());
7618
7619 EXPECT_EQ(200, response->headers->response_code());
7620 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7621
7622 std::string response_data;
7623 rv = ReadTransaction(trans.get(), &response_data);
7624 EXPECT_EQ(OK, rv);
7625 EXPECT_EQ("hello!", response_data);
7626
[email protected]029c83b62013-01-24 05:28:207627 LoadTimingInfo load_timing_info;
7628 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7629 TestLoadTimingNotReusedWithPac(load_timing_info,
7630 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7631
[email protected]7c6f7ba2012-04-03 04:09:297632 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:507633 EXPECT_TRUE(push_response->headers.get() != NULL);
[email protected]7c6f7ba2012-04-03 04:09:297634 EXPECT_EQ(200, push_response->headers->response_code());
7635
7636 rv = ReadTransaction(push_trans.get(), &response_data);
7637 EXPECT_EQ(OK, rv);
7638 EXPECT_EQ("pushed", response_data);
7639
[email protected]029c83b62013-01-24 05:28:207640 LoadTimingInfo push_load_timing_info;
7641 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
7642 TestLoadTimingReusedWithPac(push_load_timing_info);
7643 // The transactions should share a socket ID, despite being for different
7644 // origins.
7645 EXPECT_EQ(load_timing_info.socket_log_id,
7646 push_load_timing_info.socket_log_id);
7647
[email protected]7c6f7ba2012-04-03 04:09:297648 trans.reset();
7649 push_trans.reset();
7650 session->CloseAllConnections();
7651}
7652
[email protected]8c843192012-04-05 07:15:007653// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
[email protected]23e482282013-06-14 16:08:027654TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
[email protected]8c843192012-04-05 07:15:007655 HttpRequestInfo request;
7656
7657 request.method = "GET";
bncce36dca22015-04-21 22:11:237658 request.url = GURL("http://www.example.org/");
[email protected]8c843192012-04-05 07:15:007659
[email protected]8c843192012-04-05 07:15:007660 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037661 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:517662 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077663 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:507664
7665 // Enable cross-origin push.
[email protected]bb88e1d32013-05-03 23:11:077666 session_deps_.trusted_spdy_proxy = "myproxy:70";
[email protected]61b4efc2012-04-27 18:12:507667
mmenkee65e7af2015-10-13 17:16:427668 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:007669
[email protected]cdf8f7e72013-05-23 10:56:467670 scoped_ptr<SpdyFrame> stream1_syn(
7671 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
[email protected]8c843192012-04-05 07:15:007672
7673 scoped_ptr<SpdyFrame> push_rst(
[email protected]c10b20852013-05-15 21:29:207674 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:007675
7676 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137677 CreateMockWrite(*stream1_syn, 0, ASYNC), CreateMockWrite(*push_rst, 3),
[email protected]8c843192012-04-05 07:15:007678 };
7679
7680 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027681 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8c843192012-04-05 07:15:007682
7683 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027684 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]8c843192012-04-05 07:15:007685
7686 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027687 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]8c843192012-04-05 07:15:007688 0,
7689 2,
7690 1,
7691 "https://www.another-origin.com/foo.dat"));
7692
7693 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137694 CreateMockRead(*stream1_reply, 1, ASYNC),
7695 CreateMockRead(*stream2_syn, 2, ASYNC),
7696 CreateMockRead(*stream1_body, 4, ASYNC),
7697 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
[email protected]8c843192012-04-05 07:15:007698 };
7699
rch8e6c6c42015-05-01 14:05:137700 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7701 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077702 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:007703 // Negotiate SPDY to the proxy
7704 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387705 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077706 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:007707
[email protected]262eec82013-03-19 21:01:367708 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507709 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c843192012-04-05 07:15:007710 TestCompletionCallback callback;
7711 int rv = trans->Start(&request, callback.callback(), log.bound());
7712 EXPECT_EQ(ERR_IO_PENDING, rv);
7713
7714 rv = callback.WaitForResult();
7715 EXPECT_EQ(OK, rv);
7716 const HttpResponseInfo* response = trans->GetResponseInfo();
7717
7718 ASSERT_TRUE(response != NULL);
7719 EXPECT_TRUE(response->headers->IsKeepAlive());
7720
7721 EXPECT_EQ(200, response->headers->response_code());
7722 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7723
7724 std::string response_data;
7725 rv = ReadTransaction(trans.get(), &response_data);
7726 EXPECT_EQ(OK, rv);
7727 EXPECT_EQ("hello!", response_data);
7728
7729 trans.reset();
7730 session->CloseAllConnections();
7731}
7732
[email protected]2df19bb2010-08-25 20:13:467733// Test HTTPS connections to a site with a bad certificate, going through an
7734// HTTPS proxy
[email protected]23e482282013-06-14 16:08:027735TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037736 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]2df19bb2010-08-25 20:13:467737
7738 HttpRequestInfo request;
7739 request.method = "GET";
bncce36dca22015-04-21 22:11:237740 request.url = GURL("https://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467741 request.load_flags = 0;
7742
7743 // Attempt to fetch the URL from a server with a bad cert
7744 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:177745 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7746 "Host: www.example.org:443\r\n"
7747 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467748 };
7749
7750 MockRead bad_cert_reads[] = {
7751 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067752 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:467753 };
7754
7755 // Attempt to fetch the URL with a good cert
7756 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177757 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7758 "Host: www.example.org:443\r\n"
7759 "Proxy-Connection: keep-alive\r\n\r\n"),
7760 MockWrite("GET / HTTP/1.1\r\n"
7761 "Host: www.example.org\r\n"
7762 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467763 };
7764
7765 MockRead good_cert_reads[] = {
7766 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7767 MockRead("HTTP/1.0 200 OK\r\n"),
7768 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7769 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067770 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467771 };
7772
7773 StaticSocketDataProvider ssl_bad_certificate(
7774 bad_cert_reads, arraysize(bad_cert_reads),
7775 bad_cert_writes, arraysize(bad_cert_writes));
7776 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
7777 good_data_writes, arraysize(good_data_writes));
[email protected]8ddf8322012-02-23 18:08:067778 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7779 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:467780
7781 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:077782 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7783 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7784 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:467785
7786 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:077787 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7788 session_deps_.socket_factory->AddSocketDataProvider(&data);
7789 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:467790
[email protected]49639fa2011-12-20 23:22:417791 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:467792
mmenkee65e7af2015-10-13 17:16:427793 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:467794 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417795 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2df19bb2010-08-25 20:13:467796
[email protected]49639fa2011-12-20 23:22:417797 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:467798 EXPECT_EQ(ERR_IO_PENDING, rv);
7799
7800 rv = callback.WaitForResult();
7801 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7802
[email protected]49639fa2011-12-20 23:22:417803 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]2df19bb2010-08-25 20:13:467804 EXPECT_EQ(ERR_IO_PENDING, rv);
7805
7806 rv = callback.WaitForResult();
7807 EXPECT_EQ(OK, rv);
7808
7809 const HttpResponseInfo* response = trans->GetResponseInfo();
7810
[email protected]fe2255a2011-09-20 19:37:507811 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:467812 EXPECT_EQ(100, response->headers->GetContentLength());
7813}
7814
[email protected]23e482282013-06-14 16:08:027815TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:427816 HttpRequestInfo request;
7817 request.method = "GET";
bncce36dca22015-04-21 22:11:237818 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:437819 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7820 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:427821
mmenkee65e7af2015-10-13 17:16:427822 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277823 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417824 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277825
[email protected]1c773ea12009-04-28 19:58:427826 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237827 MockWrite(
7828 "GET / HTTP/1.1\r\n"
7829 "Host: www.example.org\r\n"
7830 "Connection: keep-alive\r\n"
7831 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:427832 };
7833
7834 // Lastly, the server responds with the actual content.
7835 MockRead data_reads[] = {
7836 MockRead("HTTP/1.0 200 OK\r\n"),
7837 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7838 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067839 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:427840 };
7841
[email protected]31a2bfe2010-02-09 08:03:397842 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7843 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:077844 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:427845
[email protected]49639fa2011-12-20 23:22:417846 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:427847
[email protected]49639fa2011-12-20 23:22:417848 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:427849 EXPECT_EQ(ERR_IO_PENDING, rv);
7850
7851 rv = callback.WaitForResult();
7852 EXPECT_EQ(OK, rv);
7853}
7854
[email protected]23e482282013-06-14 16:08:027855TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:297856 HttpRequestInfo request;
7857 request.method = "GET";
bncce36dca22015-04-21 22:11:237858 request.url = GURL("https://www.example.org/");
[email protected]da81f132010-08-18 23:39:297859 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7860 "Chromium Ultra Awesome X Edition");
7861
rdsmith82957ad2015-09-16 19:42:037862 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:427863 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277864 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417865 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277866
[email protected]da81f132010-08-18 23:39:297867 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177868 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7869 "Host: www.example.org:443\r\n"
7870 "Proxy-Connection: keep-alive\r\n"
7871 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]da81f132010-08-18 23:39:297872 };
7873 MockRead data_reads[] = {
7874 // Return an error, so the transaction stops here (this test isn't
7875 // interested in the rest).
7876 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7877 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7878 MockRead("Proxy-Connection: close\r\n\r\n"),
7879 };
7880
7881 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7882 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:077883 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:297884
[email protected]49639fa2011-12-20 23:22:417885 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:297886
[email protected]49639fa2011-12-20 23:22:417887 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]da81f132010-08-18 23:39:297888 EXPECT_EQ(ERR_IO_PENDING, rv);
7889
7890 rv = callback.WaitForResult();
7891 EXPECT_EQ(OK, rv);
7892}
7893
[email protected]23e482282013-06-14 16:08:027894TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:427895 HttpRequestInfo request;
7896 request.method = "GET";
bncce36dca22015-04-21 22:11:237897 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:427898 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:167899 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
7900 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:427901
mmenkee65e7af2015-10-13 17:16:427902 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277903 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417904 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277905
[email protected]1c773ea12009-04-28 19:58:427906 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237907 MockWrite(
7908 "GET / HTTP/1.1\r\n"
7909 "Host: www.example.org\r\n"
7910 "Connection: keep-alive\r\n"
7911 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:427912 };
7913
7914 // Lastly, the server responds with the actual content.
7915 MockRead data_reads[] = {
7916 MockRead("HTTP/1.0 200 OK\r\n"),
7917 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7918 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067919 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:427920 };
7921
[email protected]31a2bfe2010-02-09 08:03:397922 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7923 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:077924 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:427925
[email protected]49639fa2011-12-20 23:22:417926 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:427927
[email protected]49639fa2011-12-20 23:22:417928 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:427929 EXPECT_EQ(ERR_IO_PENDING, rv);
7930
7931 rv = callback.WaitForResult();
7932 EXPECT_EQ(OK, rv);
7933}
7934
[email protected]23e482282013-06-14 16:08:027935TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:427936 HttpRequestInfo request;
7937 request.method = "POST";
bncce36dca22015-04-21 22:11:237938 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:427939
mmenkee65e7af2015-10-13 17:16:427940 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277941 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417942 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277943
[email protected]1c773ea12009-04-28 19:58:427944 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237945 MockWrite(
7946 "POST / HTTP/1.1\r\n"
7947 "Host: www.example.org\r\n"
7948 "Connection: keep-alive\r\n"
7949 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:427950 };
7951
7952 // Lastly, the server responds with the actual content.
7953 MockRead data_reads[] = {
7954 MockRead("HTTP/1.0 200 OK\r\n"),
7955 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7956 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067957 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:427958 };
7959
[email protected]31a2bfe2010-02-09 08:03:397960 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7961 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:077962 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:427963
[email protected]49639fa2011-12-20 23:22:417964 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:427965
[email protected]49639fa2011-12-20 23:22:417966 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:427967 EXPECT_EQ(ERR_IO_PENDING, rv);
7968
7969 rv = callback.WaitForResult();
7970 EXPECT_EQ(OK, rv);
7971}
7972
[email protected]23e482282013-06-14 16:08:027973TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:427974 HttpRequestInfo request;
7975 request.method = "PUT";
bncce36dca22015-04-21 22:11:237976 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:427977
mmenkee65e7af2015-10-13 17:16:427978 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277979 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417980 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277981
[email protected]1c773ea12009-04-28 19:58:427982 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237983 MockWrite(
7984 "PUT / HTTP/1.1\r\n"
7985 "Host: www.example.org\r\n"
7986 "Connection: keep-alive\r\n"
7987 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:427988 };
7989
7990 // Lastly, the server responds with the actual content.
7991 MockRead data_reads[] = {
7992 MockRead("HTTP/1.0 200 OK\r\n"),
7993 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7994 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067995 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:427996 };
7997
[email protected]31a2bfe2010-02-09 08:03:397998 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7999 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078000 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428001
[email protected]49639fa2011-12-20 23:22:418002 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428003
[email protected]49639fa2011-12-20 23:22:418004 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428005 EXPECT_EQ(ERR_IO_PENDING, rv);
8006
8007 rv = callback.WaitForResult();
8008 EXPECT_EQ(OK, rv);
8009}
8010
[email protected]23e482282013-06-14 16:08:028011TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428012 HttpRequestInfo request;
8013 request.method = "HEAD";
bncce36dca22015-04-21 22:11:238014 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428015
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]1c773ea12009-04-28 19:58:428020 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:138021 MockWrite("HEAD / HTTP/1.1\r\n"
8022 "Host: www.example.org\r\n"
8023 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428024 };
8025
8026 // Lastly, the server responds with the actual content.
8027 MockRead data_reads[] = {
8028 MockRead("HTTP/1.0 200 OK\r\n"),
8029 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8030 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068031 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428032 };
8033
[email protected]31a2bfe2010-02-09 08:03:398034 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]1c773ea12009-04-28 19:58:428037
[email protected]49639fa2011-12-20 23:22:418038 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428039
[email protected]49639fa2011-12-20 23:22:418040 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428041 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_CacheControlNoCache) {
[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 = LOAD_BYPASS_CACHE;
8052
mmenkee65e7af2015-10-13 17:16:428053 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278054 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418055 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278056
[email protected]1c773ea12009-04-28 19:58:428057 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238058 MockWrite(
8059 "GET / HTTP/1.1\r\n"
8060 "Host: www.example.org\r\n"
8061 "Connection: keep-alive\r\n"
8062 "Pragma: no-cache\r\n"
8063 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428064 };
8065
8066 // Lastly, the server responds with the actual content.
8067 MockRead data_reads[] = {
8068 MockRead("HTTP/1.0 200 OK\r\n"),
8069 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8070 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068071 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428072 };
8073
[email protected]31a2bfe2010-02-09 08:03:398074 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8075 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078076 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428077
[email protected]49639fa2011-12-20 23:22:418078 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428079
[email protected]49639fa2011-12-20 23:22:418080 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428081 EXPECT_EQ(ERR_IO_PENDING, rv);
8082
8083 rv = callback.WaitForResult();
8084 EXPECT_EQ(OK, rv);
8085}
8086
[email protected]23e482282013-06-14 16:08:028087TEST_P(HttpNetworkTransactionTest,
[email protected]1c773ea12009-04-28 19:58:428088 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:428089 HttpRequestInfo request;
8090 request.method = "GET";
bncce36dca22015-04-21 22:11:238091 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428092 request.load_flags = LOAD_VALIDATE_CACHE;
8093
mmenkee65e7af2015-10-13 17:16:428094 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278095 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418096 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278097
[email protected]1c773ea12009-04-28 19:58:428098 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238099 MockWrite(
8100 "GET / HTTP/1.1\r\n"
8101 "Host: www.example.org\r\n"
8102 "Connection: keep-alive\r\n"
8103 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428104 };
8105
8106 // Lastly, the server responds with the actual content.
8107 MockRead data_reads[] = {
8108 MockRead("HTTP/1.0 200 OK\r\n"),
8109 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8110 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068111 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428112 };
8113
[email protected]31a2bfe2010-02-09 08:03:398114 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8115 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078116 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428117
[email protected]49639fa2011-12-20 23:22:418118 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428119
[email protected]49639fa2011-12-20 23:22:418120 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428121 EXPECT_EQ(ERR_IO_PENDING, rv);
8122
8123 rv = callback.WaitForResult();
8124 EXPECT_EQ(OK, rv);
8125}
8126
[email protected]23e482282013-06-14 16:08:028127TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:428128 HttpRequestInfo request;
8129 request.method = "GET";
bncce36dca22015-04-21 22:11:238130 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438131 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:428132
mmenkee65e7af2015-10-13 17:16:428133 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278134 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418135 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278136
[email protected]1c773ea12009-04-28 19:58:428137 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238138 MockWrite(
8139 "GET / HTTP/1.1\r\n"
8140 "Host: www.example.org\r\n"
8141 "Connection: keep-alive\r\n"
8142 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428143 };
8144
8145 // Lastly, the server responds with the actual content.
8146 MockRead data_reads[] = {
8147 MockRead("HTTP/1.0 200 OK\r\n"),
8148 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8149 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068150 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428151 };
8152
[email protected]31a2bfe2010-02-09 08:03:398153 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8154 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078155 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428156
[email protected]49639fa2011-12-20 23:22:418157 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428158
[email protected]49639fa2011-12-20 23:22:418159 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428160 EXPECT_EQ(ERR_IO_PENDING, rv);
8161
8162 rv = callback.WaitForResult();
8163 EXPECT_EQ(OK, rv);
8164}
8165
[email protected]23e482282013-06-14 16:08:028166TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:478167 HttpRequestInfo request;
8168 request.method = "GET";
bncce36dca22015-04-21 22:11:238169 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438170 request.extra_headers.SetHeader("referer", "www.foo.com");
8171 request.extra_headers.SetHeader("hEllo", "Kitty");
8172 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:478173
mmenkee65e7af2015-10-13 17:16:428174 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278175 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418176 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278177
[email protected]270c6412010-03-29 22:02:478178 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238179 MockWrite(
8180 "GET / HTTP/1.1\r\n"
8181 "Host: www.example.org\r\n"
8182 "Connection: keep-alive\r\n"
8183 "referer: www.foo.com\r\n"
8184 "hEllo: Kitty\r\n"
8185 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:478186 };
8187
8188 // Lastly, the server responds with the actual content.
8189 MockRead data_reads[] = {
8190 MockRead("HTTP/1.0 200 OK\r\n"),
8191 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8192 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068193 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:478194 };
8195
8196 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8197 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078198 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:478199
[email protected]49639fa2011-12-20 23:22:418200 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:478201
[email protected]49639fa2011-12-20 23:22:418202 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]270c6412010-03-29 22:02:478203 EXPECT_EQ(ERR_IO_PENDING, rv);
8204
8205 rv = callback.WaitForResult();
8206 EXPECT_EQ(OK, rv);
8207}
8208
[email protected]23e482282013-06-14 16:08:028209TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278210 HttpRequestInfo request;
8211 request.method = "GET";
bncce36dca22015-04-21 22:11:238212 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278213 request.load_flags = 0;
8214
rdsmith82957ad2015-09-16 19:42:038215 session_deps_.proxy_service =
8216 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518217 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078218 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028219
mmenkee65e7af2015-10-13 17:16:428220 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3cd17242009-06-23 02:59:028221 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418222 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028223
[email protected]3cd17242009-06-23 02:59:028224 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8225 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8226
8227 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238228 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8229 MockWrite(
8230 "GET / HTTP/1.1\r\n"
8231 "Host: www.example.org\r\n"
8232 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028233
8234 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:068235 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:028236 MockRead("HTTP/1.0 200 OK\r\n"),
8237 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8238 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068239 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028240 };
8241
[email protected]31a2bfe2010-02-09 08:03:398242 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8243 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078244 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028245
[email protected]49639fa2011-12-20 23:22:418246 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028247
[email protected]49639fa2011-12-20 23:22:418248 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:028249 EXPECT_EQ(ERR_IO_PENDING, rv);
8250
8251 rv = callback.WaitForResult();
8252 EXPECT_EQ(OK, rv);
8253
8254 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508255 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:028256
[email protected]029c83b62013-01-24 05:28:208257 LoadTimingInfo load_timing_info;
8258 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8259 TestLoadTimingNotReusedWithPac(load_timing_info,
8260 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8261
[email protected]3cd17242009-06-23 02:59:028262 std::string response_text;
8263 rv = ReadTransaction(trans.get(), &response_text);
8264 EXPECT_EQ(OK, rv);
8265 EXPECT_EQ("Payload", response_text);
8266}
8267
[email protected]23e482282013-06-14 16:08:028268TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278269 HttpRequestInfo request;
8270 request.method = "GET";
bncce36dca22015-04-21 22:11:238271 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278272 request.load_flags = 0;
8273
rdsmith82957ad2015-09-16 19:42:038274 session_deps_.proxy_service =
8275 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518276 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078277 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028278
mmenkee65e7af2015-10-13 17:16:428279 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3cd17242009-06-23 02:59:028280 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418281 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028282
[email protected]3cd17242009-06-23 02:59:028283 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
8284 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8285
8286 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238287 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
8288 arraysize(write_buffer)),
8289 MockWrite(
8290 "GET / HTTP/1.1\r\n"
8291 "Host: www.example.org\r\n"
8292 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028293
8294 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018295 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
8296 arraysize(read_buffer)),
[email protected]e0c27be2009-07-15 13:09:358297 MockRead("HTTP/1.0 200 OK\r\n"),
8298 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8299 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068300 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358301 };
8302
[email protected]31a2bfe2010-02-09 08:03:398303 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8304 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078305 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358306
[email protected]8ddf8322012-02-23 18:08:068307 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078308 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:358309
[email protected]49639fa2011-12-20 23:22:418310 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358311
[email protected]49639fa2011-12-20 23:22:418312 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:358313 EXPECT_EQ(ERR_IO_PENDING, rv);
8314
8315 rv = callback.WaitForResult();
8316 EXPECT_EQ(OK, rv);
8317
[email protected]029c83b62013-01-24 05:28:208318 LoadTimingInfo load_timing_info;
8319 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8320 TestLoadTimingNotReusedWithPac(load_timing_info,
8321 CONNECT_TIMING_HAS_SSL_TIMES);
8322
[email protected]e0c27be2009-07-15 13:09:358323 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508324 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:358325
8326 std::string response_text;
8327 rv = ReadTransaction(trans.get(), &response_text);
8328 EXPECT_EQ(OK, rv);
8329 EXPECT_EQ("Payload", response_text);
8330}
8331
[email protected]23e482282013-06-14 16:08:028332TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:208333 HttpRequestInfo request;
8334 request.method = "GET";
bncce36dca22015-04-21 22:11:238335 request.url = GURL("http://www.example.org/");
[email protected]029c83b62013-01-24 05:28:208336 request.load_flags = 0;
8337
rdsmith82957ad2015-09-16 19:42:038338 session_deps_.proxy_service =
8339 ProxyService::CreateFixed("socks4://myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518340 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078341 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:208342
mmenkee65e7af2015-10-13 17:16:428343 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:208344 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418345 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:208346
8347 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8348 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8349
8350 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238351 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8352 MockWrite(
8353 "GET / HTTP/1.1\r\n"
8354 "Host: www.example.org\r\n"
8355 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:208356
8357 MockRead data_reads[] = {
8358 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
8359 MockRead("HTTP/1.0 200 OK\r\n"),
8360 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8361 MockRead("Payload"),
8362 MockRead(SYNCHRONOUS, OK)
8363 };
8364
8365 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8366 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078367 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:208368
8369 TestCompletionCallback callback;
8370
8371 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8372 EXPECT_EQ(ERR_IO_PENDING, rv);
8373
8374 rv = callback.WaitForResult();
8375 EXPECT_EQ(OK, rv);
8376
8377 const HttpResponseInfo* response = trans->GetResponseInfo();
8378 ASSERT_TRUE(response != NULL);
8379
8380 LoadTimingInfo load_timing_info;
8381 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8382 TestLoadTimingNotReused(load_timing_info,
8383 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8384
8385 std::string response_text;
8386 rv = ReadTransaction(trans.get(), &response_text);
8387 EXPECT_EQ(OK, rv);
8388 EXPECT_EQ("Payload", response_text);
8389}
8390
[email protected]23e482282013-06-14 16:08:028391TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278392 HttpRequestInfo request;
8393 request.method = "GET";
bncce36dca22015-04-21 22:11:238394 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278395 request.load_flags = 0;
8396
rdsmith82957ad2015-09-16 19:42:038397 session_deps_.proxy_service =
8398 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518399 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078400 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358401
mmenkee65e7af2015-10-13 17:16:428402 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e0c27be2009-07-15 13:09:358403 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418404 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358405
[email protected]e0c27be2009-07-15 13:09:358406 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8407 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378408 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238409 0x05, // Version
8410 0x01, // Command (CONNECT)
8411 0x00, // Reserved.
8412 0x03, // Address type (DOMAINNAME).
8413 0x0F, // Length of domain (15)
8414 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8415 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:378416 };
[email protected]e0c27be2009-07-15 13:09:358417 const char kSOCKS5OkResponse[] =
8418 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
8419
8420 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238421 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8422 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
8423 MockWrite(
8424 "GET / HTTP/1.1\r\n"
8425 "Host: www.example.org\r\n"
8426 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358427
8428 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018429 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8430 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]e0c27be2009-07-15 13:09:358431 MockRead("HTTP/1.0 200 OK\r\n"),
8432 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8433 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068434 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358435 };
8436
[email protected]31a2bfe2010-02-09 08:03:398437 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8438 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078439 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358440
[email protected]49639fa2011-12-20 23:22:418441 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358442
[email protected]49639fa2011-12-20 23:22:418443 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:358444 EXPECT_EQ(ERR_IO_PENDING, rv);
8445
8446 rv = callback.WaitForResult();
8447 EXPECT_EQ(OK, rv);
8448
8449 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508450 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:358451
[email protected]029c83b62013-01-24 05:28:208452 LoadTimingInfo load_timing_info;
8453 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8454 TestLoadTimingNotReusedWithPac(load_timing_info,
8455 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8456
[email protected]e0c27be2009-07-15 13:09:358457 std::string response_text;
8458 rv = ReadTransaction(trans.get(), &response_text);
8459 EXPECT_EQ(OK, rv);
8460 EXPECT_EQ("Payload", response_text);
8461}
8462
[email protected]23e482282013-06-14 16:08:028463TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278464 HttpRequestInfo request;
8465 request.method = "GET";
bncce36dca22015-04-21 22:11:238466 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278467 request.load_flags = 0;
8468
rdsmith82957ad2015-09-16 19:42:038469 session_deps_.proxy_service =
8470 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518471 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078472 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358473
mmenkee65e7af2015-10-13 17:16:428474 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e0c27be2009-07-15 13:09:358475 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418476 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358477
[email protected]e0c27be2009-07-15 13:09:358478 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8479 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378480 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238481 0x05, // Version
8482 0x01, // Command (CONNECT)
8483 0x00, // Reserved.
8484 0x03, // Address type (DOMAINNAME).
8485 0x0F, // Length of domain (15)
8486 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8487 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:378488 };
8489
[email protected]e0c27be2009-07-15 13:09:358490 const char kSOCKS5OkResponse[] =
8491 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
8492
8493 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238494 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8495 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
8496 arraysize(kSOCKS5OkRequest)),
8497 MockWrite(
8498 "GET / HTTP/1.1\r\n"
8499 "Host: www.example.org\r\n"
8500 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358501
8502 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018503 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8504 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:028505 MockRead("HTTP/1.0 200 OK\r\n"),
8506 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8507 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068508 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028509 };
8510
[email protected]31a2bfe2010-02-09 08:03:398511 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8512 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078513 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028514
[email protected]8ddf8322012-02-23 18:08:068515 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078516 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:028517
[email protected]49639fa2011-12-20 23:22:418518 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028519
[email protected]49639fa2011-12-20 23:22:418520 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:028521 EXPECT_EQ(ERR_IO_PENDING, rv);
8522
8523 rv = callback.WaitForResult();
8524 EXPECT_EQ(OK, rv);
8525
8526 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508527 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:028528
[email protected]029c83b62013-01-24 05:28:208529 LoadTimingInfo load_timing_info;
8530 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8531 TestLoadTimingNotReusedWithPac(load_timing_info,
8532 CONNECT_TIMING_HAS_SSL_TIMES);
8533
[email protected]3cd17242009-06-23 02:59:028534 std::string response_text;
8535 rv = ReadTransaction(trans.get(), &response_text);
8536 EXPECT_EQ(OK, rv);
8537 EXPECT_EQ("Payload", response_text);
8538}
8539
[email protected]448d4ca52012-03-04 04:12:238540namespace {
8541
[email protected]04e5be32009-06-26 20:00:318542// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:068543
8544struct GroupNameTest {
8545 std::string proxy_server;
8546 std::string url;
8547 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:188548 bool ssl;
[email protected]2d731a32010-04-29 01:04:068549};
8550
mmenkee65e7af2015-10-13 17:16:428551scoped_ptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8a0fc822013-06-27 20:52:438552 NextProto next_proto,
[email protected]bb88e1d32013-05-03 23:11:078553 SpdySessionDependencies* session_deps_) {
mmenkee65e7af2015-10-13 17:16:428554 scoped_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:068555
[email protected]30d4c022013-07-18 22:58:168556 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:538557 session->http_server_properties();
bnccacc0992015-03-20 20:22:228558 AlternativeService alternative_service(
bnc4988e432015-03-31 03:06:258559 AlternateProtocolFromNextProto(next_proto), "", 443);
bnc7dc7e1b42015-07-28 14:43:128560 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:228561 http_server_properties->SetAlternativeService(
bnc7dc7e1b42015-07-28 14:43:128562 HostPortPair("host.with.alternate", 80), alternative_service, 1.0,
8563 expiration);
[email protected]2d731a32010-04-29 01:04:068564
8565 return session;
8566}
8567
mmenkee65e7af2015-10-13 17:16:428568int GroupNameTransactionHelper(const std::string& url,
8569 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:068570 HttpRequestInfo request;
8571 request.method = "GET";
8572 request.url = GURL(url);
8573 request.load_flags = 0;
8574
[email protected]262eec82013-03-19 21:01:368575 scoped_ptr<HttpTransaction> trans(
mmenkee65e7af2015-10-13 17:16:428576 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
[email protected]cb9bf6ca2011-01-28 13:15:278577
[email protected]49639fa2011-12-20 23:22:418578 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:068579
8580 // We do not complete this request, the dtor will clean the transaction up.
[email protected]49639fa2011-12-20 23:22:418581 return trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d731a32010-04-29 01:04:068582}
8583
[email protected]448d4ca52012-03-04 04:12:238584} // namespace
8585
[email protected]23e482282013-06-14 16:08:028586TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
[email protected]2d731a32010-04-29 01:04:068587 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238588 {
8589 "", // unused
8590 "http://www.example.org/direct",
8591 "www.example.org:80",
8592 false,
8593 },
8594 {
8595 "", // unused
8596 "http://[2001:1418:13:1::25]/direct",
8597 "[2001:1418:13:1::25]:80",
8598 false,
8599 },
[email protected]04e5be32009-06-26 20:00:318600
bncce36dca22015-04-21 22:11:238601 // SSL Tests
8602 {
8603 "", // unused
8604 "https://www.example.org/direct_ssl",
8605 "ssl/www.example.org:443",
8606 true,
8607 },
8608 {
8609 "", // unused
8610 "https://[2001:1418:13:1::25]/direct",
8611 "ssl/[2001:1418:13:1::25]:443",
8612 true,
8613 },
8614 {
8615 "", // unused
8616 "http://host.with.alternate/direct",
8617 "ssl/host.with.alternate:443",
8618 true,
8619 },
[email protected]2d731a32010-04-29 01:04:068620 };
[email protected]2ff8b312010-04-26 22:20:548621
bnc55ff9da2015-08-19 18:42:358622 session_deps_.use_alternative_services = true;
[email protected]2d731a32010-04-29 01:04:068623
viettrungluue4a8b882014-10-16 06:17:388624 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038625 session_deps_.proxy_service =
8626 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428627 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388628 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]2d731a32010-04-29 01:04:068629
mmenkee65e7af2015-10-13 17:16:428630 HttpNetworkSessionPeer peer(session.get());
[email protected]ab739042011-04-07 15:22:288631 CaptureGroupNameTransportSocketPool* transport_conn_pool =
8632 new CaptureGroupNameTransportSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138633 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348634 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]831e4a32013-11-14 02:14:448635 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8636 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028637 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
8638 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
dchenge3d1ddc2014-10-15 19:30:518639 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
[email protected]2d731a32010-04-29 01:04:068640
8641 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428642 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188643 if (tests[i].ssl)
8644 EXPECT_EQ(tests[i].expected_group_name,
8645 ssl_conn_pool->last_group_name_received());
8646 else
8647 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:288648 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:068649 }
[email protected]2d731a32010-04-29 01:04:068650}
8651
[email protected]23e482282013-06-14 16:08:028652TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
[email protected]2d731a32010-04-29 01:04:068653 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238654 {
8655 "http_proxy",
8656 "http://www.example.org/http_proxy_normal",
8657 "www.example.org:80",
8658 false,
8659 },
[email protected]2d731a32010-04-29 01:04:068660
bncce36dca22015-04-21 22:11:238661 // SSL Tests
8662 {
8663 "http_proxy",
8664 "https://www.example.org/http_connect_ssl",
8665 "ssl/www.example.org:443",
8666 true,
8667 },
[email protected]af3490e2010-10-16 21:02:298668
bncce36dca22015-04-21 22:11:238669 {
8670 "http_proxy",
8671 "http://host.with.alternate/direct",
8672 "ssl/host.with.alternate:443",
8673 true,
8674 },
[email protected]45499252013-01-23 17:12:568675
bncce36dca22015-04-21 22:11:238676 {
8677 "http_proxy",
8678 "ftp://ftp.google.com/http_proxy_normal",
8679 "ftp/ftp.google.com:21",
8680 false,
8681 },
[email protected]2d731a32010-04-29 01:04:068682 };
8683
bnc55ff9da2015-08-19 18:42:358684 session_deps_.use_alternative_services = true;
[email protected]2d731a32010-04-29 01:04:068685
viettrungluue4a8b882014-10-16 06:17:388686 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038687 session_deps_.proxy_service =
8688 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428689 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388690 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]2d731a32010-04-29 01:04:068691
mmenkee65e7af2015-10-13 17:16:428692 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:068693
[email protected]e60e47a2010-07-14 03:37:188694 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:138695 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:348696 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138697 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348698 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:028699
[email protected]831e4a32013-11-14 02:14:448700 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8701 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028702 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
8703 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchenge3d1ddc2014-10-15 19:30:518704 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
[email protected]2d731a32010-04-29 01:04:068705
8706 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428707 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188708 if (tests[i].ssl)
8709 EXPECT_EQ(tests[i].expected_group_name,
8710 ssl_conn_pool->last_group_name_received());
8711 else
8712 EXPECT_EQ(tests[i].expected_group_name,
8713 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:068714 }
[email protected]2d731a32010-04-29 01:04:068715}
8716
[email protected]23e482282013-06-14 16:08:028717TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
[email protected]2d731a32010-04-29 01:04:068718 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238719 {
8720 "socks4://socks_proxy:1080",
8721 "http://www.example.org/socks4_direct",
8722 "socks4/www.example.org:80",
8723 false,
8724 },
8725 {
8726 "socks5://socks_proxy:1080",
8727 "http://www.example.org/socks5_direct",
8728 "socks5/www.example.org:80",
8729 false,
8730 },
[email protected]2d731a32010-04-29 01:04:068731
bncce36dca22015-04-21 22:11:238732 // SSL Tests
8733 {
8734 "socks4://socks_proxy:1080",
8735 "https://www.example.org/socks4_ssl",
8736 "socks4/ssl/www.example.org:443",
8737 true,
8738 },
8739 {
8740 "socks5://socks_proxy:1080",
8741 "https://www.example.org/socks5_ssl",
8742 "socks5/ssl/www.example.org:443",
8743 true,
8744 },
[email protected]af3490e2010-10-16 21:02:298745
bncce36dca22015-04-21 22:11:238746 {
8747 "socks4://socks_proxy:1080",
8748 "http://host.with.alternate/direct",
8749 "socks4/ssl/host.with.alternate:443",
8750 true,
8751 },
[email protected]04e5be32009-06-26 20:00:318752 };
8753
bnc55ff9da2015-08-19 18:42:358754 session_deps_.use_alternative_services = true;
[email protected]2ff8b312010-04-26 22:20:548755
viettrungluue4a8b882014-10-16 06:17:388756 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038757 session_deps_.proxy_service =
8758 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428759 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388760 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]8b114dd72011-03-25 05:33:028761
mmenkee65e7af2015-10-13 17:16:428762 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:318763
[email protected]e60e47a2010-07-14 03:37:188764 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:138765 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348766 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138767 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348768 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:028769
[email protected]831e4a32013-11-14 02:14:448770 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8771 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028772 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
8773 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchenge3d1ddc2014-10-15 19:30:518774 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
[email protected]04e5be32009-06-26 20:00:318775
[email protected]262eec82013-03-19 21:01:368776 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:508777 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]04e5be32009-06-26 20:00:318778
[email protected]2d731a32010-04-29 01:04:068779 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428780 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188781 if (tests[i].ssl)
8782 EXPECT_EQ(tests[i].expected_group_name,
8783 ssl_conn_pool->last_group_name_received());
8784 else
8785 EXPECT_EQ(tests[i].expected_group_name,
8786 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:318787 }
8788}
8789
[email protected]23e482282013-06-14 16:08:028790TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:278791 HttpRequestInfo request;
8792 request.method = "GET";
bncce36dca22015-04-21 22:11:238793 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278794
rdsmith82957ad2015-09-16 19:42:038795 session_deps_.proxy_service =
8796 ProxyService::CreateFixed("myproxy:70;foobar:80");
[email protected]b59ff372009-07-15 22:04:328797
[email protected]69719062010-01-05 20:09:218798 // This simulates failure resolving all hostnames; that means we will fail
8799 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:078800 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:328801
mmenkee65e7af2015-10-13 17:16:428802 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]9172a982009-06-06 00:30:258803 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418804 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]9172a982009-06-06 00:30:258805
[email protected]49639fa2011-12-20 23:22:418806 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:258807
[email protected]49639fa2011-12-20 23:22:418808 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9172a982009-06-06 00:30:258809 EXPECT_EQ(ERR_IO_PENDING, rv);
8810
[email protected]9172a982009-06-06 00:30:258811 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:018812 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:258813}
8814
[email protected]685af592010-05-11 19:31:248815// Base test to make sure that when the load flags for a request specify to
8816// bypass the cache, the DNS cache is not used.
[email protected]23e482282013-06-14 16:08:028817void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
[email protected]bb88e1d32013-05-03 23:11:078818 int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:278819 // Issue a request, asking to bypass the cache(s).
8820 HttpRequestInfo request;
8821 request.method = "GET";
8822 request.load_flags = load_flags;
bncce36dca22015-04-21 22:11:238823 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278824
[email protected]a2c2fb92009-07-18 07:31:048825 // Select a host resolver that does caching.
[email protected]bb88e1d32013-05-03 23:11:078826 session_deps_.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:328827
mmenkee65e7af2015-10-13 17:16:428828 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:078829 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418830 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3b9cca42009-06-16 01:08:288831
bncce36dca22015-04-21 22:11:238832 // Warm up the host cache so it has an entry for "www.example.org".
[email protected]3b9cca42009-06-16 01:08:288833 AddressList addrlist;
[email protected]aa22b242011-11-16 18:58:298834 TestCompletionCallback callback;
[email protected]bb88e1d32013-05-03 23:11:078835 int rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:238836 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8837 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:478838 EXPECT_EQ(ERR_IO_PENDING, rv);
8839 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:288840 EXPECT_EQ(OK, rv);
8841
8842 // Verify that it was added to host cache, by doing a subsequent async lookup
8843 // and confirming it completes synchronously.
[email protected]bb88e1d32013-05-03 23:11:078844 rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:238845 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8846 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:328847 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:288848
bncce36dca22015-04-21 22:11:238849 // Inject a failure the next time that "www.example.org" is resolved. This way
[email protected]3b9cca42009-06-16 01:08:288850 // we can tell if the next lookup hit the cache, or the "network".
8851 // (cache --> success, "network" --> failure).
bncce36dca22015-04-21 22:11:238852 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
[email protected]3b9cca42009-06-16 01:08:288853
8854 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8855 // first read -- this won't be reached as the host resolution will fail first.
[email protected]8ddf8322012-02-23 18:08:068856 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:398857 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:078858 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:288859
[email protected]3b9cca42009-06-16 01:08:288860 // Run the request.
[email protected]49639fa2011-12-20 23:22:418861 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:288862 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:418863 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:288864
8865 // If we bypassed the cache, we would have gotten a failure while resolving
bncce36dca22015-04-21 22:11:238866 // "www.example.org".
[email protected]3b9cca42009-06-16 01:08:288867 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
8868}
8869
[email protected]685af592010-05-11 19:31:248870// There are multiple load flags that should trigger the host cache bypass.
8871// Test each in isolation:
[email protected]23e482282013-06-14 16:08:028872TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
[email protected]685af592010-05-11 19:31:248873 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
8874}
8875
[email protected]23e482282013-06-14 16:08:028876TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
[email protected]685af592010-05-11 19:31:248877 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
8878}
8879
[email protected]23e482282013-06-14 16:08:028880TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
[email protected]685af592010-05-11 19:31:248881 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
8882}
8883
[email protected]0877e3d2009-10-17 22:29:578884// Make sure we can handle an error when writing the request.
[email protected]23e482282013-06-14 16:08:028885TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:578886 HttpRequestInfo request;
8887 request.method = "GET";
8888 request.url = GURL("http://www.foo.com/");
8889 request.load_flags = 0;
8890
8891 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:068892 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:578893 };
[email protected]31a2bfe2010-02-09 08:03:398894 StaticSocketDataProvider data(NULL, 0,
8895 write_failure, arraysize(write_failure));
[email protected]bb88e1d32013-05-03 23:11:078896 session_deps_.socket_factory->AddSocketDataProvider(&data);
mmenkee65e7af2015-10-13 17:16:428897 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:578898
[email protected]49639fa2011-12-20 23:22:418899 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:578900
8901 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418902 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:578903
[email protected]49639fa2011-12-20 23:22:418904 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:578905 EXPECT_EQ(ERR_IO_PENDING, rv);
8906
8907 rv = callback.WaitForResult();
8908 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
ttuttled9dbc652015-09-29 20:00:598909
8910 IPEndPoint endpoint;
8911 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
8912 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:578913}
8914
zmo9528c9f42015-08-04 22:12:088915// Check that a connection closed after the start of the headers finishes ok.
8916TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:578917 HttpRequestInfo request;
8918 request.method = "GET";
8919 request.url = GURL("http://www.foo.com/");
8920 request.load_flags = 0;
8921
8922 MockRead data_reads[] = {
8923 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:068924 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:578925 };
8926
[email protected]31a2bfe2010-02-09 08:03:398927 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:078928 session_deps_.socket_factory->AddSocketDataProvider(&data);
mmenkee65e7af2015-10-13 17:16:428929 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:578930
[email protected]49639fa2011-12-20 23:22:418931 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:578932
8933 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418934 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:578935
[email protected]49639fa2011-12-20 23:22:418936 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:578937 EXPECT_EQ(ERR_IO_PENDING, rv);
8938
8939 rv = callback.WaitForResult();
zmo9528c9f42015-08-04 22:12:088940 EXPECT_EQ(OK, rv);
8941
8942 const HttpResponseInfo* response = trans->GetResponseInfo();
8943 ASSERT_TRUE(response != NULL);
8944
8945 EXPECT_TRUE(response->headers.get() != NULL);
8946 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8947
8948 std::string response_data;
8949 rv = ReadTransaction(trans.get(), &response_data);
8950 EXPECT_EQ(OK, rv);
8951 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:598952
8953 IPEndPoint endpoint;
8954 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
8955 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:578956}
8957
8958// Make sure that a dropped connection while draining the body for auth
8959// restart does the right thing.
[email protected]23e482282013-06-14 16:08:028960TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:578961 HttpRequestInfo request;
8962 request.method = "GET";
bncce36dca22015-04-21 22:11:238963 request.url = GURL("http://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:578964 request.load_flags = 0;
8965
8966 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238967 MockWrite(
8968 "GET / HTTP/1.1\r\n"
8969 "Host: www.example.org\r\n"
8970 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:578971 };
8972
8973 MockRead data_reads1[] = {
8974 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8975 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8976 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8977 MockRead("Content-Length: 14\r\n\r\n"),
8978 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:068979 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:578980 };
8981
[email protected]31a2bfe2010-02-09 08:03:398982 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8983 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:078984 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:578985
8986 // After calling trans->RestartWithAuth(), this is the request we should
8987 // be issuing -- the final header line contains the credentials.
8988 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238989 MockWrite(
8990 "GET / HTTP/1.1\r\n"
8991 "Host: www.example.org\r\n"
8992 "Connection: keep-alive\r\n"
8993 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:578994 };
8995
8996 // Lastly, the server responds with the actual content.
8997 MockRead data_reads2[] = {
8998 MockRead("HTTP/1.1 200 OK\r\n"),
8999 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9000 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069001 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:579002 };
9003
[email protected]31a2bfe2010-02-09 08:03:399004 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9005 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:079006 session_deps_.socket_factory->AddSocketDataProvider(&data2);
mmenkee65e7af2015-10-13 17:16:429007 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579008
[email protected]49639fa2011-12-20 23:22:419009 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:579010
[email protected]262eec82013-03-19 21:01:369011 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509012 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509013
[email protected]49639fa2011-12-20 23:22:419014 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579015 EXPECT_EQ(ERR_IO_PENDING, rv);
9016
9017 rv = callback1.WaitForResult();
9018 EXPECT_EQ(OK, rv);
9019
9020 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509021 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049022 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:579023
[email protected]49639fa2011-12-20 23:22:419024 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:579025
[email protected]49639fa2011-12-20 23:22:419026 rv = trans->RestartWithAuth(
9027 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]0877e3d2009-10-17 22:29:579028 EXPECT_EQ(ERR_IO_PENDING, rv);
9029
9030 rv = callback2.WaitForResult();
9031 EXPECT_EQ(OK, rv);
9032
9033 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509034 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:579035 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9036 EXPECT_EQ(100, response->headers->GetContentLength());
9037}
9038
9039// Test HTTPS connections going through a proxy that sends extra data.
[email protected]23e482282013-06-14 16:08:029040TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
rdsmith82957ad2015-09-16 19:42:039041 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]0877e3d2009-10-17 22:29:579042
9043 HttpRequestInfo request;
9044 request.method = "GET";
bncce36dca22015-04-21 22:11:239045 request.url = GURL("https://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:579046 request.load_flags = 0;
9047
9048 MockRead proxy_reads[] = {
9049 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:069050 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:579051 };
9052
[email protected]31a2bfe2010-02-09 08:03:399053 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]8ddf8322012-02-23 18:08:069054 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:579055
[email protected]bb88e1d32013-05-03 23:11:079056 session_deps_.socket_factory->AddSocketDataProvider(&data);
9057 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:579058
[email protected]49639fa2011-12-20 23:22:419059 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579060
[email protected]bb88e1d32013-05-03 23:11:079061 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:579062
mmenkee65e7af2015-10-13 17:16:429063 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579064 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419065 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579066
[email protected]49639fa2011-12-20 23:22:419067 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579068 EXPECT_EQ(ERR_IO_PENDING, rv);
9069
9070 rv = callback.WaitForResult();
9071 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
9072}
9073
[email protected]23e482282013-06-14 16:08:029074TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:469075 HttpRequestInfo request;
9076 request.method = "GET";
bncce36dca22015-04-21 22:11:239077 request.url = GURL("http://www.example.org/");
[email protected]9492e4a2010-02-24 00:58:469078 request.load_flags = 0;
9079
mmenkee65e7af2015-10-13 17:16:429080 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279081 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419082 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:279083
[email protected]e22e1362009-11-23 21:31:129084 MockRead data_reads[] = {
9085 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069086 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:129087 };
[email protected]9492e4a2010-02-24 00:58:469088
9089 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079090 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:469091
[email protected]49639fa2011-12-20 23:22:419092 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:469093
[email protected]49639fa2011-12-20 23:22:419094 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:469095 EXPECT_EQ(ERR_IO_PENDING, rv);
9096
9097 EXPECT_EQ(OK, callback.WaitForResult());
9098
9099 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509100 ASSERT_TRUE(response != NULL);
[email protected]9492e4a2010-02-24 00:58:469101
[email protected]90499482013-06-01 00:39:509102 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]9492e4a2010-02-24 00:58:469103 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9104
9105 std::string response_data;
9106 rv = ReadTransaction(trans.get(), &response_data);
[email protected]5543cbb2012-04-20 16:35:239107 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
[email protected]e22e1362009-11-23 21:31:129108}
9109
[email protected]23e482282013-06-14 16:08:029110TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:159111 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:529112 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
[email protected]95d88ffe2010-02-04 21:25:339113 const uint64 kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:219114 UploadFileElementReader::ScopedOverridingContentLengthForTests
9115 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:339116
olli.raula6df48b2a2015-11-26 07:40:229117 std::vector<scoped_ptr<UploadElementReader>> element_readers;
9118 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
9119 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0, kuint64max,
9120 base::Time())));
9121 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279122
9123 HttpRequestInfo request;
9124 request.method = "POST";
bncce36dca22015-04-21 22:11:239125 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279126 request.upload_data_stream = &upload_data_stream;
9127 request.load_flags = 0;
9128
mmenkee65e7af2015-10-13 17:16:429129 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]329b68b2012-11-14 17:54:279130 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419131 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]95d88ffe2010-02-04 21:25:339132
9133 MockRead data_reads[] = {
9134 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9135 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069136 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:339137 };
[email protected]31a2bfe2010-02-09 08:03:399138 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079139 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:339140
[email protected]49639fa2011-12-20 23:22:419141 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:339142
[email protected]49639fa2011-12-20 23:22:419143 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:339144 EXPECT_EQ(ERR_IO_PENDING, rv);
9145
9146 rv = callback.WaitForResult();
9147 EXPECT_EQ(OK, rv);
9148
9149 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509150 ASSERT_TRUE(response != NULL);
[email protected]95d88ffe2010-02-04 21:25:339151
[email protected]90499482013-06-01 00:39:509152 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]95d88ffe2010-02-04 21:25:339153 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9154
9155 std::string response_data;
9156 rv = ReadTransaction(trans.get(), &response_data);
9157 EXPECT_EQ(OK, rv);
9158 EXPECT_EQ("hello world", response_data);
9159
[email protected]dd3aa792013-07-16 19:10:239160 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:339161}
9162
[email protected]23e482282013-06-14 16:08:029163TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:159164 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:529165 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:369166 std::string temp_file_content("Unreadable file.");
[email protected]e5c2a22e2014-03-06 20:42:309167 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
[email protected]6624b4622010-03-29 19:58:369168 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:119169 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:369170
olli.raula6df48b2a2015-11-26 07:40:229171 std::vector<scoped_ptr<UploadElementReader>> element_readers;
9172 element_readers.push_back(make_scoped_ptr(
skyostil4891b25b2015-06-11 11:43:459173 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
olli.raula6df48b2a2015-11-26 07:40:229174 temp_file, 0, kuint64max, base::Time())));
9175 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279176
9177 HttpRequestInfo request;
9178 request.method = "POST";
bncce36dca22015-04-21 22:11:239179 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279180 request.upload_data_stream = &upload_data_stream;
9181 request.load_flags = 0;
9182
[email protected]999dd8c2013-11-12 06:45:549183 // If we try to upload an unreadable file, the transaction should fail.
mmenkee65e7af2015-10-13 17:16:429184 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]329b68b2012-11-14 17:54:279185 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419186 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]6624b4622010-03-29 19:58:369187
[email protected]999dd8c2013-11-12 06:45:549188 StaticSocketDataProvider data(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079189 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:369190
[email protected]49639fa2011-12-20 23:22:419191 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:369192
[email protected]49639fa2011-12-20 23:22:419193 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:369194 EXPECT_EQ(ERR_IO_PENDING, rv);
9195
9196 rv = callback.WaitForResult();
[email protected]999dd8c2013-11-12 06:45:549197 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
[email protected]6624b4622010-03-29 19:58:369198
[email protected]dd3aa792013-07-16 19:10:239199 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:369200}
9201
[email protected]02cad5d2013-10-02 08:14:039202TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
9203 class FakeUploadElementReader : public UploadElementReader {
9204 public:
9205 FakeUploadElementReader() {}
dchengb03027d2014-10-21 12:00:209206 ~FakeUploadElementReader() override {}
[email protected]02cad5d2013-10-02 08:14:039207
9208 const CompletionCallback& callback() const { return callback_; }
9209
9210 // UploadElementReader overrides:
dchengb03027d2014-10-21 12:00:209211 int Init(const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039212 callback_ = callback;
9213 return ERR_IO_PENDING;
9214 }
dchengb03027d2014-10-21 12:00:209215 uint64 GetContentLength() const override { return 0; }
9216 uint64 BytesRemaining() const override { return 0; }
9217 int Read(IOBuffer* buf,
9218 int buf_length,
9219 const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039220 return ERR_FAILED;
9221 }
9222
9223 private:
9224 CompletionCallback callback_;
9225 };
9226
9227 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
olli.raula6df48b2a2015-11-26 07:40:229228 std::vector<scoped_ptr<UploadElementReader>> element_readers;
9229 element_readers.push_back(make_scoped_ptr(fake_reader));
9230 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:039231
9232 HttpRequestInfo request;
9233 request.method = "POST";
bncce36dca22015-04-21 22:11:239234 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:039235 request.upload_data_stream = &upload_data_stream;
9236 request.load_flags = 0;
9237
mmenkee65e7af2015-10-13 17:16:429238 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02cad5d2013-10-02 08:14:039239 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419240 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02cad5d2013-10-02 08:14:039241
9242 StaticSocketDataProvider data;
9243 session_deps_.socket_factory->AddSocketDataProvider(&data);
9244
9245 TestCompletionCallback callback;
9246 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9247 EXPECT_EQ(ERR_IO_PENDING, rv);
9248 base::MessageLoop::current()->RunUntilIdle();
9249
9250 // Transaction is pending on request body initialization.
9251 ASSERT_FALSE(fake_reader->callback().is_null());
9252
9253 // Return Init()'s result after the transaction gets destroyed.
9254 trans.reset();
9255 fake_reader->callback().Run(OK); // Should not crash.
9256}
9257
[email protected]aeefc9e82010-02-19 16:18:279258// Tests that changes to Auth realms are treated like auth rejections.
[email protected]23e482282013-06-14 16:08:029259TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:279260 HttpRequestInfo request;
9261 request.method = "GET";
bncce36dca22015-04-21 22:11:239262 request.url = GURL("http://www.example.org/");
[email protected]aeefc9e82010-02-19 16:18:279263 request.load_flags = 0;
9264
9265 // First transaction will request a resource and receive a Basic challenge
9266 // with realm="first_realm".
9267 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239268 MockWrite(
9269 "GET / HTTP/1.1\r\n"
9270 "Host: www.example.org\r\n"
9271 "Connection: keep-alive\r\n"
9272 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279273 };
9274 MockRead data_reads1[] = {
9275 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9276 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9277 "\r\n"),
9278 };
9279
9280 // After calling trans->RestartWithAuth(), provide an Authentication header
9281 // for first_realm. The server will reject and provide a challenge with
9282 // second_realm.
9283 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239284 MockWrite(
9285 "GET / HTTP/1.1\r\n"
9286 "Host: www.example.org\r\n"
9287 "Connection: keep-alive\r\n"
9288 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
9289 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279290 };
9291 MockRead data_reads2[] = {
9292 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9293 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
9294 "\r\n"),
9295 };
9296
9297 // This again fails, and goes back to first_realm. Make sure that the
9298 // entry is removed from cache.
9299 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239300 MockWrite(
9301 "GET / HTTP/1.1\r\n"
9302 "Host: www.example.org\r\n"
9303 "Connection: keep-alive\r\n"
9304 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
9305 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279306 };
9307 MockRead data_reads3[] = {
9308 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9309 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9310 "\r\n"),
9311 };
9312
9313 // Try one last time (with the correct password) and get the resource.
9314 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:239315 MockWrite(
9316 "GET / HTTP/1.1\r\n"
9317 "Host: www.example.org\r\n"
9318 "Connection: keep-alive\r\n"
9319 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
9320 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279321 };
9322 MockRead data_reads4[] = {
9323 MockRead("HTTP/1.1 200 OK\r\n"
9324 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:509325 "Content-Length: 5\r\n"
9326 "\r\n"
9327 "hello"),
[email protected]aeefc9e82010-02-19 16:18:279328 };
9329
9330 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9331 data_writes1, arraysize(data_writes1));
9332 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9333 data_writes2, arraysize(data_writes2));
9334 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
9335 data_writes3, arraysize(data_writes3));
9336 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
9337 data_writes4, arraysize(data_writes4));
[email protected]bb88e1d32013-05-03 23:11:079338 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9339 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9340 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9341 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:279342
[email protected]49639fa2011-12-20 23:22:419343 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:279344
mmenkee65e7af2015-10-13 17:16:429345 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0b0bf032010-09-21 18:08:509346 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419347 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509348
[email protected]aeefc9e82010-02-19 16:18:279349 // Issue the first request with Authorize headers. There should be a
9350 // password prompt for first_realm waiting to be filled in after the
9351 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419352 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:279353 EXPECT_EQ(ERR_IO_PENDING, rv);
9354 rv = callback1.WaitForResult();
9355 EXPECT_EQ(OK, rv);
9356 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509357 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049358 const AuthChallengeInfo* challenge = response->auth_challenge.get();
9359 ASSERT_FALSE(challenge == NULL);
9360 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239361 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049362 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199363 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279364
9365 // Issue the second request with an incorrect password. There should be a
9366 // password prompt for second_realm waiting to be filled in after the
9367 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419368 TestCompletionCallback callback2;
9369 rv = trans->RestartWithAuth(
9370 AuthCredentials(kFirst, kBaz), callback2.callback());
[email protected]aeefc9e82010-02-19 16:18:279371 EXPECT_EQ(ERR_IO_PENDING, rv);
9372 rv = callback2.WaitForResult();
9373 EXPECT_EQ(OK, rv);
9374 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509375 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049376 challenge = response->auth_challenge.get();
9377 ASSERT_FALSE(challenge == NULL);
9378 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239379 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049380 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199381 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279382
9383 // Issue the third request with another incorrect password. There should be
9384 // a password prompt for first_realm waiting to be filled in. If the password
9385 // prompt is not present, it indicates that the HttpAuthCacheEntry for
9386 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:419387 TestCompletionCallback callback3;
9388 rv = trans->RestartWithAuth(
9389 AuthCredentials(kSecond, kFou), callback3.callback());
[email protected]aeefc9e82010-02-19 16:18:279390 EXPECT_EQ(ERR_IO_PENDING, rv);
9391 rv = callback3.WaitForResult();
9392 EXPECT_EQ(OK, rv);
9393 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509394 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049395 challenge = response->auth_challenge.get();
9396 ASSERT_FALSE(challenge == NULL);
9397 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239398 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049399 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199400 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279401
9402 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:419403 TestCompletionCallback callback4;
9404 rv = trans->RestartWithAuth(
9405 AuthCredentials(kFirst, kBar), callback4.callback());
[email protected]aeefc9e82010-02-19 16:18:279406 EXPECT_EQ(ERR_IO_PENDING, rv);
9407 rv = callback4.WaitForResult();
9408 EXPECT_EQ(OK, rv);
9409 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509410 ASSERT_TRUE(response != NULL);
[email protected]aeefc9e82010-02-19 16:18:279411 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9412}
9413
bncc958faa2015-07-31 18:14:529414TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
9415 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359416 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529417
9418 std::string alternative_service_http_header =
9419 GetAlternativeServiceHttpHeader();
9420
9421 MockRead data_reads[] = {
9422 MockRead("HTTP/1.1 200 OK\r\n"),
9423 MockRead(alternative_service_http_header.c_str()),
9424 MockRead("\r\n"),
9425 MockRead("hello world"),
9426 MockRead(SYNCHRONOUS, OK),
9427 };
9428
9429 HttpRequestInfo request;
9430 request.method = "GET";
9431 request.url = GURL("http://www.example.org/");
9432 request.load_flags = 0;
9433
9434 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9435
9436 session_deps_.socket_factory->AddSocketDataProvider(&data);
9437
9438 TestCompletionCallback callback;
9439
mmenkee65e7af2015-10-13 17:16:429440 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529441 scoped_ptr<HttpTransaction> trans(
9442 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9443
9444 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9445 EXPECT_EQ(ERR_IO_PENDING, rv);
9446
9447 HostPortPair http_host_port_pair("www.example.org", 80);
9448 HttpServerProperties& http_server_properties =
9449 *session->http_server_properties();
9450 AlternativeServiceVector alternative_service_vector =
9451 http_server_properties.GetAlternativeServices(http_host_port_pair);
9452 EXPECT_TRUE(alternative_service_vector.empty());
9453
9454 EXPECT_EQ(OK, callback.WaitForResult());
9455
9456 const HttpResponseInfo* response = trans->GetResponseInfo();
9457 ASSERT_TRUE(response != NULL);
9458 ASSERT_TRUE(response->headers.get() != NULL);
9459 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9460 EXPECT_FALSE(response->was_fetched_via_spdy);
9461 EXPECT_FALSE(response->was_npn_negotiated);
9462
9463 std::string response_data;
9464 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9465 EXPECT_EQ("hello world", response_data);
9466
9467 alternative_service_vector =
9468 http_server_properties.GetAlternativeServices(http_host_port_pair);
9469 ASSERT_EQ(1u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389470 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529471 alternative_service_vector[0].protocol);
9472 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9473 EXPECT_EQ(443, alternative_service_vector[0].port);
9474}
9475
bnc4f575852015-10-14 18:35:089476TEST_P(HttpNetworkTransactionTest, ClearAlternativeServices) {
9477 session_deps_.next_protos = SpdyNextProtos();
9478 session_deps_.use_alternative_services = true;
9479
9480 // Set an alternative service for origin.
9481 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9482 HttpServerProperties& http_server_properties =
9483 *session->http_server_properties();
9484 HostPortPair http_host_port_pair("www.example.org", 80);
9485 AlternativeService alternative_service(QUIC, "", 80);
9486 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9487 http_server_properties.SetAlternativeService(
9488 http_host_port_pair, alternative_service, 1.0, expiration);
9489 AlternativeServiceVector alternative_service_vector =
9490 http_server_properties.GetAlternativeServices(http_host_port_pair);
9491 EXPECT_EQ(1u, alternative_service_vector.size());
9492
9493 // Send a clear header.
9494 MockRead data_reads[] = {
9495 MockRead("HTTP/1.1 200 OK\r\n"),
9496 MockRead("Alt-Svc: clear\r\n"),
9497 MockRead("\r\n"),
9498 MockRead("hello world"),
9499 MockRead(SYNCHRONOUS, OK),
9500 };
9501 StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
9502 session_deps_.socket_factory->AddSocketDataProvider(&data);
9503
9504 HttpRequestInfo request;
9505 request.method = "GET";
9506 request.url = GURL("http://www.example.org/");
9507 request.load_flags = 0;
9508
9509 TestCompletionCallback callback;
9510
9511 scoped_ptr<HttpTransaction> trans(
9512 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9513
9514 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9515 EXPECT_EQ(OK, callback.GetResult(rv));
9516
9517 const HttpResponseInfo* response = trans->GetResponseInfo();
9518 ASSERT_TRUE(response != nullptr);
9519 ASSERT_TRUE(response->headers.get() != nullptr);
9520 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9521 EXPECT_FALSE(response->was_fetched_via_spdy);
9522 EXPECT_FALSE(response->was_npn_negotiated);
9523
9524 std::string response_data;
9525 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9526 EXPECT_EQ("hello world", response_data);
9527
9528 alternative_service_vector =
9529 http_server_properties.GetAlternativeServices(http_host_port_pair);
9530 EXPECT_TRUE(alternative_service_vector.empty());
9531}
9532
bnc54ec34b72015-08-26 19:34:569533// Alternative Service headers must be ignored when |use_alternative_services|
9534// is false.
9535TEST_P(HttpNetworkTransactionTest, DoNotHonorAlternativeServiceHeader) {
9536 session_deps_.next_protos = SpdyNextProtos();
9537 session_deps_.use_alternative_services = false;
9538
9539 std::string alternative_service_http_header =
9540 GetAlternativeServiceHttpHeader();
9541
9542 MockRead data_reads[] = {
9543 MockRead("HTTP/1.1 200 OK\r\n"),
9544 MockRead(alternative_service_http_header.c_str()),
9545 MockRead("\r\n"),
9546 MockRead("hello world"),
9547 MockRead(SYNCHRONOUS, OK),
9548 };
9549
9550 HttpRequestInfo request;
9551 request.method = "GET";
9552 request.url = GURL("http://www.example.org/");
9553 request.load_flags = 0;
9554
9555 StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
9556
9557 session_deps_.socket_factory->AddSocketDataProvider(&data);
9558
9559 TestCompletionCallback callback;
9560
mmenkee65e7af2015-10-13 17:16:429561 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc54ec34b72015-08-26 19:34:569562 scoped_ptr<HttpTransaction> trans(
9563 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9564
9565 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9566 EXPECT_EQ(ERR_IO_PENDING, rv);
9567
9568 HostPortPair http_host_port_pair("www.example.org", 80);
9569 HttpServerProperties& http_server_properties =
9570 *session->http_server_properties();
9571 AlternativeServiceVector alternative_service_vector =
9572 http_server_properties.GetAlternativeServices(http_host_port_pair);
9573 EXPECT_TRUE(alternative_service_vector.empty());
9574
9575 EXPECT_EQ(OK, callback.WaitForResult());
9576
9577 const HttpResponseInfo* response = trans->GetResponseInfo();
9578 ASSERT_TRUE(response != nullptr);
9579 ASSERT_TRUE(response->headers.get() != nullptr);
9580 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9581 EXPECT_FALSE(response->was_fetched_via_spdy);
9582 EXPECT_FALSE(response->was_npn_negotiated);
9583
9584 std::string response_data;
9585 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9586 EXPECT_EQ("hello world", response_data);
9587
9588 alternative_service_vector =
9589 http_server_properties.GetAlternativeServices(http_host_port_pair);
9590 EXPECT_TRUE(alternative_service_vector.empty());
9591}
9592
bncc958faa2015-07-31 18:14:529593TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) {
9594 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359595 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529596
9597 MockRead data_reads[] = {
9598 MockRead("HTTP/1.1 200 OK\r\n"),
9599 MockRead("Alt-Svc: "),
9600 MockRead(GetAlternateProtocolFromParam()),
bnc44858c82015-10-16 11:57:219601 MockRead("=\"www.example.com:443\";p=\"1.0\","),
bncc958faa2015-07-31 18:14:529602 MockRead("quic=\":1234\"\r\n\r\n"),
9603 MockRead("hello world"),
9604 MockRead(SYNCHRONOUS, OK),
9605 };
9606
9607 HttpRequestInfo request;
9608 request.method = "GET";
9609 request.url = GURL("http://www.example.org/");
9610 request.load_flags = 0;
9611
9612 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9613
9614 session_deps_.socket_factory->AddSocketDataProvider(&data);
9615
9616 TestCompletionCallback callback;
9617
mmenkee65e7af2015-10-13 17:16:429618 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529619 scoped_ptr<HttpTransaction> trans(
9620 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9621
9622 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9623 EXPECT_EQ(ERR_IO_PENDING, rv);
9624
9625 HostPortPair http_host_port_pair("www.example.org", 80);
9626 HttpServerProperties& http_server_properties =
9627 *session->http_server_properties();
9628 AlternativeServiceVector alternative_service_vector =
9629 http_server_properties.GetAlternativeServices(http_host_port_pair);
9630 EXPECT_TRUE(alternative_service_vector.empty());
9631
9632 EXPECT_EQ(OK, callback.WaitForResult());
9633
9634 const HttpResponseInfo* response = trans->GetResponseInfo();
9635 ASSERT_TRUE(response != NULL);
9636 ASSERT_TRUE(response->headers.get() != NULL);
9637 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9638 EXPECT_FALSE(response->was_fetched_via_spdy);
9639 EXPECT_FALSE(response->was_npn_negotiated);
9640
9641 std::string response_data;
9642 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9643 EXPECT_EQ("hello world", response_data);
9644
9645 alternative_service_vector =
9646 http_server_properties.GetAlternativeServices(http_host_port_pair);
9647 ASSERT_EQ(2u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389648 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529649 alternative_service_vector[0].protocol);
9650 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9651 EXPECT_EQ(443, alternative_service_vector[0].port);
9652 EXPECT_EQ(QUIC, alternative_service_vector[1].protocol);
9653 EXPECT_EQ("www.example.org", alternative_service_vector[1].host);
9654 EXPECT_EQ(1234, alternative_service_vector[1].port);
9655}
9656
bnc54ec34b72015-08-26 19:34:569657// Alternate Protocol headers must be honored even if |use_alternative_services|
9658// is false.
[email protected]23e482282013-06-14 16:08:029659TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]d7599122014-05-24 03:37:239660 session_deps_.next_protos = SpdyNextProtos();
bnc54ec34b72015-08-26 19:34:569661 session_deps_.use_alternative_services = false;
[email protected]a2cb8122010-03-10 17:22:429662
[email protected]8a0fc822013-06-27 20:52:439663 std::string alternate_protocol_http_header =
9664 GetAlternateProtocolHttpHeader();
9665
[email protected]564b4912010-03-09 16:30:429666 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:529667 MockRead("HTTP/1.1 200 OK\r\n"),
9668 MockRead(alternate_protocol_http_header.c_str()),
9669 MockRead("\r\n"),
9670 MockRead("hello world"),
9671 MockRead(SYNCHRONOUS, OK),
[email protected]564b4912010-03-09 16:30:429672 };
9673
9674 HttpRequestInfo request;
9675 request.method = "GET";
bncce36dca22015-04-21 22:11:239676 request.url = GURL("http://www.example.org/");
[email protected]564b4912010-03-09 16:30:429677 request.load_flags = 0;
9678
9679 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9680
[email protected]bb88e1d32013-05-03 23:11:079681 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]564b4912010-03-09 16:30:429682
[email protected]49639fa2011-12-20 23:22:419683 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:429684
mmenkee65e7af2015-10-13 17:16:429685 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:369686 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509687 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]564b4912010-03-09 16:30:429688
[email protected]49639fa2011-12-20 23:22:419689 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:429690 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:539691
bncce36dca22015-04-21 22:11:239692 HostPortPair http_host_port_pair("www.example.org", 80);
[email protected]9801e3702014-03-07 09:33:559693 HttpServerProperties& http_server_properties =
[email protected]17291a022011-10-10 07:32:539694 *session->http_server_properties();
bncd9b132e2015-07-08 05:16:109695 AlternativeServiceVector alternative_service_vector =
9696 http_server_properties.GetAlternativeServices(http_host_port_pair);
9697 EXPECT_TRUE(alternative_service_vector.empty());
[email protected]564b4912010-03-09 16:30:429698
9699 EXPECT_EQ(OK, callback.WaitForResult());
9700
9701 const HttpResponseInfo* response = trans->GetResponseInfo();
9702 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:509703 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]564b4912010-03-09 16:30:429704 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:539705 EXPECT_FALSE(response->was_fetched_via_spdy);
9706 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:429707
9708 std::string response_data;
9709 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9710 EXPECT_EQ("hello world", response_data);
9711
bncd9b132e2015-07-08 05:16:109712 alternative_service_vector =
9713 http_server_properties.GetAlternativeServices(http_host_port_pair);
9714 ASSERT_EQ(1u, alternative_service_vector.size());
9715 EXPECT_EQ(443, alternative_service_vector[0].port);
rdsmithebb50aa2015-11-12 03:44:389716 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncd9b132e2015-07-08 05:16:109717 alternative_service_vector[0].protocol);
[email protected]564b4912010-03-09 16:30:429718}
9719
rch89c6e102015-03-18 18:56:529720TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
9721 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359722 session_deps_.use_alternative_services = true;
rch89c6e102015-03-18 18:56:529723
9724 MockRead data_reads[] = {
9725 MockRead("HTTP/1.1 200 OK\r\n"),
9726 MockRead("Alternate-Protocol: \r\n\r\n"),
9727 MockRead("hello world"),
9728 MockRead(SYNCHRONOUS, OK),
9729 };
9730
9731 HttpRequestInfo request;
9732 request.method = "GET";
bncce36dca22015-04-21 22:11:239733 request.url = GURL("http://www.example.org/");
rch89c6e102015-03-18 18:56:529734 request.load_flags = 0;
9735
9736 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9737
9738 session_deps_.socket_factory->AddSocketDataProvider(&data);
9739
9740 TestCompletionCallback callback;
9741
mmenkee65e7af2015-10-13 17:16:429742 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rch89c6e102015-03-18 18:56:529743
bncce36dca22015-04-21 22:11:239744 HostPortPair http_host_port_pair("www.example.org", 80);
rch89c6e102015-03-18 18:56:529745 HttpServerProperties& http_server_properties =
9746 *session->http_server_properties();
bnccacc0992015-03-20 20:22:229747 AlternativeService alternative_service(QUIC, "", 80);
bnc7dc7e1b42015-07-28 14:43:129748 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9749 http_server_properties.SetAlternativeService(
9750 http_host_port_pair, alternative_service, 1.0, expiration);
bnccacc0992015-03-20 20:22:229751
bncd9b132e2015-07-08 05:16:109752 AlternativeServiceVector alternative_service_vector =
9753 http_server_properties.GetAlternativeServices(http_host_port_pair);
9754 ASSERT_EQ(1u, alternative_service_vector.size());
9755 EXPECT_EQ(QUIC, alternative_service_vector[0].protocol);
rch89c6e102015-03-18 18:56:529756
9757 scoped_ptr<HttpTransaction> trans(
9758 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9759
9760 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9761 EXPECT_EQ(ERR_IO_PENDING, rv);
9762
9763 EXPECT_EQ(OK, callback.WaitForResult());
9764
9765 const HttpResponseInfo* response = trans->GetResponseInfo();
9766 ASSERT_TRUE(response != NULL);
9767 ASSERT_TRUE(response->headers.get() != NULL);
9768 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9769 EXPECT_FALSE(response->was_fetched_via_spdy);
9770 EXPECT_FALSE(response->was_npn_negotiated);
9771
9772 std::string response_data;
9773 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9774 EXPECT_EQ("hello world", response_data);
9775
bncd9b132e2015-07-08 05:16:109776 alternative_service_vector =
9777 http_server_properties.GetAlternativeServices(http_host_port_pair);
9778 EXPECT_TRUE(alternative_service_vector.empty());
rch89c6e102015-03-18 18:56:529779}
9780
bncc958faa2015-07-31 18:14:529781TEST_P(HttpNetworkTransactionTest, AltSvcOverwritesAlternateProtocol) {
9782 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359783 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529784
9785 std::string alternative_service_http_header =
9786 GetAlternativeServiceHttpHeader();
9787 std::string alternate_protocol_http_header = GetAlternateProtocolHttpHeader();
9788
9789 MockRead data_reads[] = {
9790 MockRead("HTTP/1.1 200 OK\r\n"),
9791 MockRead(alternative_service_http_header.c_str()),
9792 MockRead(alternate_protocol_http_header.c_str()),
9793 MockRead("\r\n"),
9794 MockRead("hello world"),
9795 MockRead(SYNCHRONOUS, OK),
9796 };
9797
9798 HttpRequestInfo request;
9799 request.method = "GET";
9800 request.url = GURL("http://www.example.org/");
9801 request.load_flags = 0;
9802
9803 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9804
9805 session_deps_.socket_factory->AddSocketDataProvider(&data);
9806
9807 TestCompletionCallback callback;
9808
mmenkee65e7af2015-10-13 17:16:429809 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529810 scoped_ptr<HttpTransaction> trans(
9811 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9812
9813 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9814 EXPECT_EQ(ERR_IO_PENDING, rv);
9815
9816 HostPortPair http_host_port_pair("www.example.org", 80);
9817 HttpServerProperties& http_server_properties =
9818 *session->http_server_properties();
9819 AlternativeServiceVector alternative_service_vector =
9820 http_server_properties.GetAlternativeServices(http_host_port_pair);
9821 EXPECT_TRUE(alternative_service_vector.empty());
9822
9823 EXPECT_EQ(OK, callback.WaitForResult());
9824
9825 const HttpResponseInfo* response = trans->GetResponseInfo();
9826 ASSERT_TRUE(response != NULL);
9827 ASSERT_TRUE(response->headers.get() != NULL);
9828 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9829 EXPECT_FALSE(response->was_fetched_via_spdy);
9830 EXPECT_FALSE(response->was_npn_negotiated);
9831
9832 std::string response_data;
9833 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9834 EXPECT_EQ("hello world", response_data);
9835
9836 alternative_service_vector =
9837 http_server_properties.GetAlternativeServices(http_host_port_pair);
9838 ASSERT_EQ(1u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389839 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529840 alternative_service_vector[0].protocol);
9841 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9842 EXPECT_EQ(443, alternative_service_vector[0].port);
9843}
9844
bnc54ec34b72015-08-26 19:34:569845// When |use_alternative_services| is false, do not observe alternative service
9846// entries that point to a different host.
9847TEST_P(HttpNetworkTransactionTest, DisableAlternativeServiceToDifferentHost) {
9848 session_deps_.use_alternative_services = false;
9849
9850 HttpRequestInfo request;
9851 request.method = "GET";
9852 request.url = GURL("http://www.example.org/");
9853 request.load_flags = 0;
9854
9855 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9856 StaticSocketDataProvider first_data;
9857 first_data.set_connect_data(mock_connect);
9858 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9859
9860 MockRead data_reads[] = {
9861 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
9862 MockRead(ASYNC, OK),
9863 };
9864 StaticSocketDataProvider second_data(data_reads, arraysize(data_reads),
9865 nullptr, 0);
9866 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9867
mmenkee65e7af2015-10-13 17:16:429868 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc54ec34b72015-08-26 19:34:569869
9870 base::WeakPtr<HttpServerProperties> http_server_properties =
9871 session->http_server_properties();
9872 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:389873 AlternateProtocolFromNextProto(GetProtocol()), "different.example.org",
9874 80);
bnc54ec34b72015-08-26 19:34:569875 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9876 http_server_properties->SetAlternativeService(
9877 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
9878
9879 scoped_ptr<HttpTransaction> trans(
9880 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9881 TestCompletionCallback callback;
9882
9883 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9884 // The connetion to origin was refused, and the alternative service should not
9885 // be used (even though mock data are there), therefore the request should
9886 // fail.
9887 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.GetResult(rv));
9888}
9889
[email protected]23e482282013-06-14 16:08:029890TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:239891 MarkBrokenAlternateProtocolAndFallback) {
bnc55ff9da2015-08-19 18:42:359892 session_deps_.use_alternative_services = true;
[email protected]564b4912010-03-09 16:30:429893
9894 HttpRequestInfo request;
9895 request.method = "GET";
bncce36dca22015-04-21 22:11:239896 request.url = GURL("http://www.example.org/");
[email protected]564b4912010-03-09 16:30:429897 request.load_flags = 0;
9898
[email protected]d973e99a2012-02-17 21:02:369899 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:429900 StaticSocketDataProvider first_data;
9901 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:079902 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]564b4912010-03-09 16:30:429903
9904 MockRead data_reads[] = {
9905 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9906 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069907 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:429908 };
9909 StaticSocketDataProvider second_data(
9910 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079911 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:429912
mmenkee65e7af2015-10-13 17:16:429913 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:429914
[email protected]30d4c022013-07-18 22:58:169915 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:539916 session->http_server_properties();
bnc8445b3002015-03-13 01:57:099917 const HostPortPair host_port_pair = HostPortPair::FromURL(request.url);
[email protected]3912662a32011-10-04 00:51:119918 // Port must be < 1024, or the header will be ignored (since initial port was
9919 // port 80 (another restricted port).
bncd9b132e2015-07-08 05:16:109920 const AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:389921 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bncd9b132e2015-07-08 05:16:109922 666); // Port is ignored by MockConnect anyway.
bnc7dc7e1b42015-07-28 14:43:129923 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9924 http_server_properties->SetAlternativeService(
9925 host_port_pair, alternative_service, 1.0, expiration);
[email protected]564b4912010-03-09 16:30:429926
[email protected]262eec82013-03-19 21:01:369927 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509928 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:419929 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:429930
[email protected]49639fa2011-12-20 23:22:419931 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:429932 EXPECT_EQ(ERR_IO_PENDING, rv);
9933 EXPECT_EQ(OK, callback.WaitForResult());
9934
9935 const HttpResponseInfo* response = trans->GetResponseInfo();
9936 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:509937 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]564b4912010-03-09 16:30:429938 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9939
9940 std::string response_data;
9941 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9942 EXPECT_EQ("hello world", response_data);
9943
bncd9b132e2015-07-08 05:16:109944 const AlternativeServiceVector alternative_service_vector =
9945 http_server_properties->GetAlternativeServices(host_port_pair);
9946 ASSERT_EQ(1u, alternative_service_vector.size());
9947 EXPECT_EQ(alternative_service, alternative_service_vector[0]);
9948 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
9949 alternative_service_vector[0]));
[email protected]564b4912010-03-09 16:30:429950}
9951
bnc55ff9da2015-08-19 18:42:359952// Ensure that we are not allowed to redirect traffic via an alternate protocol
9953// to an unrestricted (port >= 1024) when the original traffic was on a
9954// restricted port (port < 1024). Ensure that we can redirect in all other
9955// cases.
[email protected]23e482282013-06-14 16:08:029956TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:239957 AlternateProtocolPortRestrictedBlocked) {
bnc55ff9da2015-08-19 18:42:359958 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:119959
9960 HttpRequestInfo restricted_port_request;
9961 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:239962 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:119963 restricted_port_request.load_flags = 0;
9964
[email protected]d973e99a2012-02-17 21:02:369965 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:119966 StaticSocketDataProvider first_data;
9967 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:079968 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:119969
9970 MockRead data_reads[] = {
9971 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9972 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069973 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:119974 };
9975 StaticSocketDataProvider second_data(
9976 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079977 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:119978
mmenkee65e7af2015-10-13 17:16:429979 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:119980
[email protected]30d4c022013-07-18 22:58:169981 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:539982 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:119983 const int kUnrestrictedAlternatePort = 1024;
bnccacc0992015-03-20 20:22:229984 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:389985 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:229986 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:129987 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:229988 http_server_properties->SetAlternativeService(
9989 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:129990 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:119991
[email protected]262eec82013-03-19 21:01:369992 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509993 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:419994 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:119995
[email protected]49639fa2011-12-20 23:22:419996 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:369997 &restricted_port_request,
9998 callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:119999 EXPECT_EQ(ERR_IO_PENDING, rv);
10000 // Invalid change to unrestricted port should fail.
10001 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
[email protected]c54c6962013-02-01 04:53:1910002}
[email protected]3912662a32011-10-04 00:51:1110003
bnc55ff9da2015-08-19 18:42:3510004// Ensure that we are allowed to redirect traffic via an alternate protocol to
10005// an unrestricted (port >= 1024) when the original traffic was on a restricted
10006// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
[email protected]23e482282013-06-14 16:08:0210007TEST_P(HttpNetworkTransactionTest,
[email protected]c54c6962013-02-01 04:53:1910008 AlternateProtocolPortRestrictedPermitted) {
bnc55ff9da2015-08-19 18:42:3510009 session_deps_.use_alternative_services = true;
[email protected]bb88e1d32013-05-03 23:11:0710010 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1910011
10012 HttpRequestInfo restricted_port_request;
10013 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310014 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1910015 restricted_port_request.load_flags = 0;
10016
10017 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
10018 StaticSocketDataProvider first_data;
10019 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710020 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1910021
10022 MockRead data_reads[] = {
10023 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10024 MockRead("hello world"),
10025 MockRead(ASYNC, OK),
10026 };
10027 StaticSocketDataProvider second_data(
10028 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710029 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]c54c6962013-02-01 04:53:1910030
mmenkee65e7af2015-10-13 17:16:4210031 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1910032
[email protected]30d4c022013-07-18 22:58:1610033 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]c54c6962013-02-01 04:53:1910034 session->http_server_properties();
10035 const int kUnrestrictedAlternatePort = 1024;
bnccacc0992015-03-20 20:22:2210036 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810037 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210038 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210039 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210040 http_server_properties->SetAlternativeService(
10041 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210042 1.0, expiration);
[email protected]c54c6962013-02-01 04:53:1910043
[email protected]262eec82013-03-19 21:01:3610044 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010045 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]c54c6962013-02-01 04:53:1910046 TestCompletionCallback callback;
10047
10048 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
[email protected]262eec82013-03-19 21:01:3610049 &restricted_port_request,
10050 callback.callback(), BoundNetLog()));
[email protected]c54c6962013-02-01 04:53:1910051 // Change to unrestricted port should succeed.
10052 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110053}
10054
bnc55ff9da2015-08-19 18:42:3510055// Ensure that we are not allowed to redirect traffic via an alternate protocol
10056// to an unrestricted (port >= 1024) when the original traffic was on a
10057// restricted port (port < 1024). Ensure that we can redirect in all other
10058// cases.
[email protected]23e482282013-06-14 16:08:0210059TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310060 AlternateProtocolPortRestrictedAllowed) {
bnc55ff9da2015-08-19 18:42:3510061 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110062
10063 HttpRequestInfo restricted_port_request;
10064 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310065 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1110066 restricted_port_request.load_flags = 0;
10067
[email protected]d973e99a2012-02-17 21:02:3610068 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110069 StaticSocketDataProvider first_data;
10070 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710071 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110072
10073 MockRead data_reads[] = {
10074 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10075 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610076 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110077 };
10078 StaticSocketDataProvider second_data(
10079 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710080 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110081
mmenkee65e7af2015-10-13 17:16:4210082 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110083
[email protected]30d4c022013-07-18 22:58:1610084 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310085 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110086 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210087 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810088 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210089 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210090 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210091 http_server_properties->SetAlternativeService(
10092 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210093 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110094
[email protected]262eec82013-03-19 21:01:3610095 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010096 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110097 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110098
[email protected]49639fa2011-12-20 23:22:4110099 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:3610100 &restricted_port_request,
10101 callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110102 EXPECT_EQ(ERR_IO_PENDING, rv);
10103 // Valid change to restricted port should pass.
10104 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110105}
10106
bnc55ff9da2015-08-19 18:42:3510107// Ensure that we are not allowed to redirect traffic via an alternate protocol
10108// to an unrestricted (port >= 1024) when the original traffic was on a
10109// restricted port (port < 1024). Ensure that we can redirect in all other
10110// cases.
[email protected]23e482282013-06-14 16:08:0210111TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310112 AlternateProtocolPortUnrestrictedAllowed1) {
bnc55ff9da2015-08-19 18:42:3510113 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110114
10115 HttpRequestInfo unrestricted_port_request;
10116 unrestricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310117 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110118 unrestricted_port_request.load_flags = 0;
10119
[email protected]d973e99a2012-02-17 21:02:3610120 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110121 StaticSocketDataProvider first_data;
10122 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710123 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110124
10125 MockRead data_reads[] = {
10126 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10127 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610128 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110129 };
10130 StaticSocketDataProvider second_data(
10131 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710132 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110133
mmenkee65e7af2015-10-13 17:16:4210134 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110135
[email protected]30d4c022013-07-18 22:58:1610136 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310137 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110138 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210139 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810140 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210141 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210142 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210143 http_server_properties->SetAlternativeService(
10144 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210145 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110146
[email protected]262eec82013-03-19 21:01:3610147 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010148 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110149 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110150
[email protected]49639fa2011-12-20 23:22:4110151 int rv = trans->Start(
10152 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110153 EXPECT_EQ(ERR_IO_PENDING, rv);
10154 // Valid change to restricted port should pass.
10155 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110156}
10157
bnc55ff9da2015-08-19 18:42:3510158// Ensure that we are not allowed to redirect traffic via an alternate protocol
10159// to an unrestricted (port >= 1024) when the original traffic was on a
10160// restricted port (port < 1024). Ensure that we can redirect in all other
10161// cases.
[email protected]23e482282013-06-14 16:08:0210162TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310163 AlternateProtocolPortUnrestrictedAllowed2) {
bnc55ff9da2015-08-19 18:42:3510164 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110165
10166 HttpRequestInfo unrestricted_port_request;
10167 unrestricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310168 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110169 unrestricted_port_request.load_flags = 0;
10170
[email protected]d973e99a2012-02-17 21:02:3610171 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110172 StaticSocketDataProvider first_data;
10173 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710174 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110175
10176 MockRead data_reads[] = {
10177 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10178 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610179 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110180 };
10181 StaticSocketDataProvider second_data(
10182 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710183 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110184
mmenkee65e7af2015-10-13 17:16:4210185 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110186
[email protected]30d4c022013-07-18 22:58:1610187 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310188 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2210189 const int kUnrestrictedAlternatePort = 1025;
bnccacc0992015-03-20 20:22:2210190 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810191 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210192 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210193 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210194 http_server_properties->SetAlternativeService(
10195 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210196 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110197
[email protected]262eec82013-03-19 21:01:3610198 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010199 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110200 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110201
[email protected]49639fa2011-12-20 23:22:4110202 int rv = trans->Start(
10203 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110204 EXPECT_EQ(ERR_IO_PENDING, rv);
10205 // Valid change to an unrestricted port should pass.
10206 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110207}
10208
bnc55ff9da2015-08-19 18:42:3510209// Ensure that we are not allowed to redirect traffic via an alternate protocol
10210// to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
10211// once the alternate protocol request fails.
[email protected]d7599122014-05-24 03:37:2310212TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
bnc55ff9da2015-08-19 18:42:3510213 session_deps_.use_alternative_services = true;
[email protected]eb6234e2012-01-19 01:50:0210214
10215 HttpRequestInfo request;
10216 request.method = "GET";
bncce36dca22015-04-21 22:11:2310217 request.url = GURL("http://www.example.org/");
[email protected]eb6234e2012-01-19 01:50:0210218 request.load_flags = 0;
10219
10220 // The alternate protocol request will error out before we attempt to connect,
10221 // so only the standard HTTP request will try to connect.
10222 MockRead data_reads[] = {
10223 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10224 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610225 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0210226 };
10227 StaticSocketDataProvider data(
10228 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710229 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0210230
mmenkee65e7af2015-10-13 17:16:4210231 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0210232
[email protected]30d4c022013-07-18 22:58:1610233 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0210234 session->http_server_properties();
10235 const int kUnsafePort = 7;
bnccacc0992015-03-20 20:22:2210236 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810237 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210238 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1210239 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210240 http_server_properties->SetAlternativeService(
bnc7dc7e1b42015-07-28 14:43:1210241 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
[email protected]eb6234e2012-01-19 01:50:0210242
[email protected]262eec82013-03-19 21:01:3610243 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010244 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]eb6234e2012-01-19 01:50:0210245 TestCompletionCallback callback;
10246
10247 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10248 EXPECT_EQ(ERR_IO_PENDING, rv);
10249 // The HTTP request should succeed.
10250 EXPECT_EQ(OK, callback.WaitForResult());
10251
[email protected]eb6234e2012-01-19 01:50:0210252 const HttpResponseInfo* response = trans->GetResponseInfo();
10253 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010254 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]eb6234e2012-01-19 01:50:0210255 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10256
10257 std::string response_data;
10258 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10259 EXPECT_EQ("hello world", response_data);
10260}
10261
[email protected]23e482282013-06-14 16:08:0210262TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510263 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310264 session_deps_.next_protos = SpdyNextProtos();
[email protected]2ff8b312010-04-26 22:20:5410265
10266 HttpRequestInfo request;
10267 request.method = "GET";
bncce36dca22015-04-21 22:11:2310268 request.url = GURL("http://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5410269 request.load_flags = 0;
10270
[email protected]8a0fc822013-06-27 20:52:4310271 std::string alternate_protocol_http_header =
10272 GetAlternateProtocolHttpHeader();
10273
[email protected]2ff8b312010-04-26 22:20:5410274 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210275 MockRead("HTTP/1.1 200 OK\r\n"),
10276 MockRead(alternate_protocol_http_header.c_str()),
10277 MockRead("\r\n"),
10278 MockRead("hello world"),
10279 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10280 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5410281
10282 StaticSocketDataProvider first_transaction(
10283 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710284 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2ff8b312010-04-26 22:20:5410285
[email protected]8ddf8322012-02-23 18:08:0610286 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810287 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310288 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10289 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710290 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2ff8b312010-04-26 22:20:5410291
[email protected]cdf8f7e72013-05-23 10:56:4610292 scoped_ptr<SpdyFrame> req(
10293 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1310294 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]2ff8b312010-04-26 22:20:5410295
[email protected]23e482282013-06-14 16:08:0210296 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10297 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5410298 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310299 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5410300 };
10301
rch8e6c6c42015-05-01 14:05:1310302 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10303 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710304 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5410305
[email protected]d973e99a2012-02-17 21:02:3610306 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510307 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10308 NULL, 0, NULL, 0);
10309 hanging_non_alternate_protocol_socket.set_connect_data(
10310 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710311 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510312 &hanging_non_alternate_protocol_socket);
10313
[email protected]49639fa2011-12-20 23:22:4110314 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5410315
mmenkee65e7af2015-10-13 17:16:4210316 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610317 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010318 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410319
[email protected]49639fa2011-12-20 23:22:4110320 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410321 EXPECT_EQ(ERR_IO_PENDING, rv);
10322 EXPECT_EQ(OK, callback.WaitForResult());
10323
10324 const HttpResponseInfo* response = trans->GetResponseInfo();
10325 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010326 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5410327 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10328
10329 std::string response_data;
10330 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10331 EXPECT_EQ("hello world", response_data);
10332
[email protected]90499482013-06-01 00:39:5010333 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410334
[email protected]49639fa2011-12-20 23:22:4110335 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410336 EXPECT_EQ(ERR_IO_PENDING, rv);
10337 EXPECT_EQ(OK, callback.WaitForResult());
10338
10339 response = trans->GetResponseInfo();
10340 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010341 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210342 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310343 EXPECT_TRUE(response->was_fetched_via_spdy);
10344 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5410345
10346 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10347 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5410348}
10349
[email protected]23e482282013-06-14 16:08:0210350TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
bnc55ff9da2015-08-19 18:42:3510351 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310352 session_deps_.next_protos = SpdyNextProtos();
[email protected]2d6728692011-03-12 01:39:5510353
10354 HttpRequestInfo request;
10355 request.method = "GET";
bncce36dca22015-04-21 22:11:2310356 request.url = GURL("http://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510357 request.load_flags = 0;
10358
[email protected]8a0fc822013-06-27 20:52:4310359 std::string alternate_protocol_http_header =
10360 GetAlternateProtocolHttpHeader();
10361
[email protected]2d6728692011-03-12 01:39:5510362 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210363 MockRead("HTTP/1.1 200 OK\r\n"),
10364 MockRead(alternate_protocol_http_header.c_str()),
10365 MockRead("\r\n"),
10366 MockRead("hello world"),
10367 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10368 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510369 };
10370
10371 StaticSocketDataProvider first_transaction(
10372 data_reads, arraysize(data_reads), NULL, 0);
10373 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
[email protected]bb88e1d32013-05-03 23:11:0710374 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510375
[email protected]d973e99a2012-02-17 21:02:3610376 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510377 StaticSocketDataProvider hanging_socket(
10378 NULL, 0, NULL, 0);
10379 hanging_socket.set_connect_data(never_finishing_connect);
10380 // Socket 2 and 3 are the hanging Alternate-Protocol and
10381 // non-Alternate-Protocol jobs from the 2nd transaction.
[email protected]bb88e1d32013-05-03 23:11:0710382 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
10383 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
[email protected]2d6728692011-03-12 01:39:5510384
[email protected]8ddf8322012-02-23 18:08:0610385 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810386 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310387 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10388 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710389 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510390
[email protected]cdf8f7e72013-05-23 10:56:4610391 scoped_ptr<SpdyFrame> req1(
10392 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10393 scoped_ptr<SpdyFrame> req2(
10394 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]2d6728692011-03-12 01:39:5510395 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1310396 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
[email protected]2d6728692011-03-12 01:39:5510397 };
[email protected]23e482282013-06-14 16:08:0210398 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10399 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
10400 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10401 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5510402 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310403 CreateMockRead(*resp1, 2),
10404 CreateMockRead(*data1, 3),
10405 CreateMockRead(*resp2, 4),
10406 CreateMockRead(*data2, 5),
10407 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5510408 };
10409
rch8e6c6c42015-05-01 14:05:1310410 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10411 arraysize(spdy_writes));
[email protected]2d6728692011-03-12 01:39:5510412 // Socket 4 is the successful Alternate-Protocol for transaction 3.
[email protected]bb88e1d32013-05-03 23:11:0710413 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5510414
10415 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
[email protected]bb88e1d32013-05-03 23:11:0710416 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
[email protected]2d6728692011-03-12 01:39:5510417
mmenkee65e7af2015-10-13 17:16:4210418 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4110419 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5010420 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5510421
[email protected]49639fa2011-12-20 23:22:4110422 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510423 EXPECT_EQ(ERR_IO_PENDING, rv);
10424 EXPECT_EQ(OK, callback1.WaitForResult());
10425
10426 const HttpResponseInfo* response = trans1.GetResponseInfo();
10427 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010428 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510429 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10430
10431 std::string response_data;
10432 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10433 EXPECT_EQ("hello world", response_data);
10434
[email protected]49639fa2011-12-20 23:22:4110435 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5010436 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110437 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510438 EXPECT_EQ(ERR_IO_PENDING, rv);
10439
[email protected]49639fa2011-12-20 23:22:4110440 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5010441 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110442 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510443 EXPECT_EQ(ERR_IO_PENDING, rv);
10444
10445 EXPECT_EQ(OK, callback2.WaitForResult());
10446 EXPECT_EQ(OK, callback3.WaitForResult());
10447
10448 response = trans2.GetResponseInfo();
10449 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010450 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210451 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5510452 EXPECT_TRUE(response->was_fetched_via_spdy);
10453 EXPECT_TRUE(response->was_npn_negotiated);
10454 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10455 EXPECT_EQ("hello!", response_data);
10456
10457 response = trans3.GetResponseInfo();
10458 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010459 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210460 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5510461 EXPECT_TRUE(response->was_fetched_via_spdy);
10462 EXPECT_TRUE(response->was_npn_negotiated);
10463 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
10464 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5510465}
10466
[email protected]23e482282013-06-14 16:08:0210467TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510468 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310469 session_deps_.next_protos = SpdyNextProtos();
[email protected]2d6728692011-03-12 01:39:5510470
10471 HttpRequestInfo request;
10472 request.method = "GET";
bncce36dca22015-04-21 22:11:2310473 request.url = GURL("http://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510474 request.load_flags = 0;
10475
[email protected]8a0fc822013-06-27 20:52:4310476 std::string alternate_protocol_http_header =
10477 GetAlternateProtocolHttpHeader();
10478
[email protected]2d6728692011-03-12 01:39:5510479 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210480 MockRead("HTTP/1.1 200 OK\r\n"),
10481 MockRead(alternate_protocol_http_header.c_str()),
10482 MockRead("\r\n"),
10483 MockRead("hello world"),
10484 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10485 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510486 };
10487
10488 StaticSocketDataProvider first_transaction(
10489 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710490 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510491
[email protected]8ddf8322012-02-23 18:08:0610492 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810493 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0710494 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510495
[email protected]d973e99a2012-02-17 21:02:3610496 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510497 StaticSocketDataProvider hanging_alternate_protocol_socket(
10498 NULL, 0, NULL, 0);
10499 hanging_alternate_protocol_socket.set_connect_data(
10500 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710501 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510502 &hanging_alternate_protocol_socket);
10503
10504 // 2nd request is just a copy of the first one, over HTTP again.
[email protected]bb88e1d32013-05-03 23:11:0710505 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510506
[email protected]49639fa2011-12-20 23:22:4110507 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5510508
mmenkee65e7af2015-10-13 17:16:4210509 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610510 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010511 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510512
[email protected]49639fa2011-12-20 23:22:4110513 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510514 EXPECT_EQ(ERR_IO_PENDING, rv);
10515 EXPECT_EQ(OK, callback.WaitForResult());
10516
10517 const HttpResponseInfo* response = trans->GetResponseInfo();
10518 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010519 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510520 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10521
10522 std::string response_data;
10523 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10524 EXPECT_EQ("hello world", response_data);
10525
[email protected]90499482013-06-01 00:39:5010526 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510527
[email protected]49639fa2011-12-20 23:22:4110528 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510529 EXPECT_EQ(ERR_IO_PENDING, rv);
10530 EXPECT_EQ(OK, callback.WaitForResult());
10531
10532 response = trans->GetResponseInfo();
10533 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010534 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510535 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10536 EXPECT_FALSE(response->was_fetched_via_spdy);
10537 EXPECT_FALSE(response->was_npn_negotiated);
10538
10539 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10540 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5510541}
10542
[email protected]631f1322010-04-30 17:59:1110543class CapturingProxyResolver : public ProxyResolver {
10544 public:
sammce90c9212015-05-27 23:43:3510545 CapturingProxyResolver() {}
dchengb03027d2014-10-21 12:00:2010546 ~CapturingProxyResolver() override {}
[email protected]631f1322010-04-30 17:59:1110547
dchengb03027d2014-10-21 12:00:2010548 int GetProxyForURL(const GURL& url,
10549 ProxyInfo* results,
10550 const CompletionCallback& callback,
10551 RequestHandle* request,
10552 const BoundNetLog& net_log) override {
[email protected]fae7669f2010-08-02 21:49:4010553 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
10554 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:4210555 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:1110556 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:4210557 return OK;
[email protected]631f1322010-04-30 17:59:1110558 }
10559
dchengb03027d2014-10-21 12:00:2010560 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
[email protected]631f1322010-04-30 17:59:1110561
dchengb03027d2014-10-21 12:00:2010562 LoadState GetLoadState(RequestHandle request) const override {
[email protected]f2c971f2011-11-08 00:33:1710563 NOTREACHED();
10564 return LOAD_STATE_IDLE;
10565 }
10566
[email protected]24476402010-07-20 20:55:1710567 const std::vector<GURL>& resolved() const { return resolved_; }
10568
10569 private:
[email protected]631f1322010-04-30 17:59:1110570 std::vector<GURL> resolved_;
10571
10572 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
10573};
10574
sammce64b2362015-04-29 03:50:2310575class CapturingProxyResolverFactory : public ProxyResolverFactory {
10576 public:
10577 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
10578 : ProxyResolverFactory(false), resolver_(resolver) {}
10579
10580 int CreateProxyResolver(
10581 const scoped_refptr<ProxyResolverScriptData>& pac_script,
10582 scoped_ptr<ProxyResolver>* resolver,
10583 const net::CompletionCallback& callback,
10584 scoped_ptr<Request>* request) override {
10585 resolver->reset(new ForwardingProxyResolver(resolver_));
10586 return OK;
10587 }
10588
10589 private:
10590 ProxyResolver* resolver_;
10591};
10592
[email protected]23e482282013-06-14 16:08:0210593TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310594 UseAlternateProtocolForTunneledNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510595 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310596 session_deps_.next_protos = SpdyNextProtos();
[email protected]631f1322010-04-30 17:59:1110597
10598 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4210599 proxy_config.set_auto_detect(true);
10600 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1110601
sammc5dd160c2015-04-02 02:43:1310602 CapturingProxyResolver capturing_proxy_resolver;
[email protected]bb88e1d32013-05-03 23:11:0710603 session_deps_.proxy_service.reset(new ProxyService(
csharrisonb7e3a082015-09-22 19:13:0410604 make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)),
sammc5dd160c2015-04-02 02:43:1310605 make_scoped_ptr(
sammce64b2362015-04-29 03:50:2310606 new CapturingProxyResolverFactory(&capturing_proxy_resolver)),
[email protected]66761b952010-06-25 21:30:3810607 NULL));
vishal.b62985ca92015-04-17 08:45:5110608 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710609 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1110610
10611 HttpRequestInfo request;
10612 request.method = "GET";
bncce36dca22015-04-21 22:11:2310613 request.url = GURL("http://www.example.org/");
[email protected]631f1322010-04-30 17:59:1110614 request.load_flags = 0;
10615
[email protected]8a0fc822013-06-27 20:52:4310616 std::string alternate_protocol_http_header =
10617 GetAlternateProtocolHttpHeader();
10618
[email protected]631f1322010-04-30 17:59:1110619 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210620 MockRead("HTTP/1.1 200 OK\r\n"),
10621 MockRead(alternate_protocol_http_header.c_str()),
10622 MockRead("\r\n"),
10623 MockRead("hello world"),
10624 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10625 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1110626 };
10627
10628 StaticSocketDataProvider first_transaction(
10629 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710630 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]631f1322010-04-30 17:59:1110631
[email protected]8ddf8322012-02-23 18:08:0610632 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810633 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310634 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10635 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710636 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]631f1322010-04-30 17:59:1110637
[email protected]cdf8f7e72013-05-23 10:56:4610638 scoped_ptr<SpdyFrame> req(
10639 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]631f1322010-04-30 17:59:1110640 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1310641 MockWrite(ASYNC, 0,
10642 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1710643 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1310644 "Proxy-Connection: keep-alive\r\n\r\n"),
10645 CreateMockWrite(*req, 2),
[email protected]631f1322010-04-30 17:59:1110646 };
10647
[email protected]d911f1b2010-05-05 22:39:4210648 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10649
[email protected]23e482282013-06-14 16:08:0210650 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10651 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:1110652 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310653 MockRead(ASYNC, 1, kCONNECTResponse),
10654 CreateMockRead(*resp.get(), 3),
10655 CreateMockRead(*data.get(), 4),
10656 MockRead(ASYNC, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1110657 };
10658
rch8e6c6c42015-05-01 14:05:1310659 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10660 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710661 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1110662
[email protected]d973e99a2012-02-17 21:02:3610663 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510664 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10665 NULL, 0, NULL, 0);
10666 hanging_non_alternate_protocol_socket.set_connect_data(
10667 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710668 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510669 &hanging_non_alternate_protocol_socket);
10670
[email protected]49639fa2011-12-20 23:22:4110671 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1110672
mmenkee65e7af2015-10-13 17:16:4210673 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610674 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010675 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1110676
[email protected]49639fa2011-12-20 23:22:4110677 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:1110678 EXPECT_EQ(ERR_IO_PENDING, rv);
10679 EXPECT_EQ(OK, callback.WaitForResult());
10680
10681 const HttpResponseInfo* response = trans->GetResponseInfo();
10682 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010683 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]631f1322010-04-30 17:59:1110684 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310685 EXPECT_FALSE(response->was_fetched_via_spdy);
10686 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:1110687
10688 std::string response_data;
10689 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10690 EXPECT_EQ("hello world", response_data);
10691
[email protected]90499482013-06-01 00:39:5010692 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1110693
[email protected]49639fa2011-12-20 23:22:4110694 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:1110695 EXPECT_EQ(ERR_IO_PENDING, rv);
10696 EXPECT_EQ(OK, callback.WaitForResult());
10697
10698 response = trans->GetResponseInfo();
10699 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010700 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210701 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310702 EXPECT_TRUE(response->was_fetched_via_spdy);
10703 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:1110704
10705 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10706 EXPECT_EQ("hello!", response_data);
sammc5dd160c2015-04-02 02:43:1310707 ASSERT_EQ(3u, capturing_proxy_resolver.resolved().size());
bncce36dca22015-04-21 22:11:2310708 EXPECT_EQ("http://www.example.org/",
sammc5dd160c2015-04-02 02:43:1310709 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2310710 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1310711 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1110712
[email protected]029c83b62013-01-24 05:28:2010713 LoadTimingInfo load_timing_info;
10714 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10715 TestLoadTimingNotReusedWithPac(load_timing_info,
10716 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1110717}
[email protected]631f1322010-04-30 17:59:1110718
[email protected]23e482282013-06-14 16:08:0210719TEST_P(HttpNetworkTransactionTest,
[email protected]2ff8b312010-04-26 22:20:5410720 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
bnc55ff9da2015-08-19 18:42:3510721 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310722 session_deps_.next_protos = SpdyNextProtos();
[email protected]2ff8b312010-04-26 22:20:5410723
10724 HttpRequestInfo request;
10725 request.method = "GET";
bncce36dca22015-04-21 22:11:2310726 request.url = GURL("http://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5410727 request.load_flags = 0;
10728
[email protected]8a0fc822013-06-27 20:52:4310729 std::string alternate_protocol_http_header =
10730 GetAlternateProtocolHttpHeader();
10731
[email protected]2ff8b312010-04-26 22:20:5410732 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210733 MockRead("HTTP/1.1 200 OK\r\n"),
10734 MockRead(alternate_protocol_http_header.c_str()),
10735 MockRead("\r\n"),
10736 MockRead("hello world"),
10737 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5410738 };
10739
10740 StaticSocketDataProvider first_transaction(
10741 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710742 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2ff8b312010-04-26 22:20:5410743
[email protected]8ddf8322012-02-23 18:08:0610744 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810745 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310746 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10747 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710748 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2ff8b312010-04-26 22:20:5410749
[email protected]cdf8f7e72013-05-23 10:56:4610750 scoped_ptr<SpdyFrame> req(
10751 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1310752 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]2ff8b312010-04-26 22:20:5410753
[email protected]23e482282013-06-14 16:08:0210754 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10755 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5410756 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310757 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5410758 };
10759
rch8e6c6c42015-05-01 14:05:1310760 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10761 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710762 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5410763
[email protected]83039bb2011-12-09 18:43:5510764 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5410765
mmenkee65e7af2015-10-13 17:16:4210766 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5410767
[email protected]262eec82013-03-19 21:01:3610768 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010769 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410770
[email protected]49639fa2011-12-20 23:22:4110771 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410772 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4110773 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:5410774
10775 const HttpResponseInfo* response = trans->GetResponseInfo();
10776 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010777 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5410778 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10779
10780 std::string response_data;
10781 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10782 EXPECT_EQ("hello world", response_data);
10783
10784 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2310785 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4010786 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5310787 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2710788 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:4210789 CreateSecureSpdySession(session.get(), key, BoundNetLog());
[email protected]02b0c342010-09-25 21:09:3810790
[email protected]90499482013-06-01 00:39:5010791 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410792
[email protected]49639fa2011-12-20 23:22:4110793 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410794 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4110795 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:5410796
10797 response = trans->GetResponseInfo();
10798 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010799 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210800 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310801 EXPECT_TRUE(response->was_fetched_via_spdy);
10802 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5410803
10804 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10805 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4210806}
10807
[email protected]044de0642010-06-17 10:42:1510808// GenerateAuthToken is a mighty big test.
10809// It tests all permutation of GenerateAuthToken behavior:
10810// - Synchronous and Asynchronous completion.
10811// - OK or error on completion.
10812// - Direct connection, non-authenticating proxy, and authenticating proxy.
10813// - HTTP or HTTPS backend (to include proxy tunneling).
10814// - Non-authenticating and authenticating backend.
10815//
[email protected]fe3b7dc2012-02-03 19:52:0910816// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1510817// problems generating an auth token for an authenticating proxy, we don't
10818// need to test all permutations of the backend server).
10819//
10820// The test proceeds by going over each of the configuration cases, and
10821// potentially running up to three rounds in each of the tests. The TestConfig
10822// specifies both the configuration for the test as well as the expectations
10823// for the results.
[email protected]23e482282013-06-14 16:08:0210824TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5010825 static const char kServer[] = "http://www.example.com";
10826 static const char kSecureServer[] = "https://www.example.com";
10827 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1510828 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
10829
10830 enum AuthTiming {
10831 AUTH_NONE,
10832 AUTH_SYNC,
10833 AUTH_ASYNC,
10834 };
10835
10836 const MockWrite kGet(
10837 "GET / HTTP/1.1\r\n"
10838 "Host: www.example.com\r\n"
10839 "Connection: keep-alive\r\n\r\n");
10840 const MockWrite kGetProxy(
10841 "GET http://www.example.com/ HTTP/1.1\r\n"
10842 "Host: www.example.com\r\n"
10843 "Proxy-Connection: keep-alive\r\n\r\n");
10844 const MockWrite kGetAuth(
10845 "GET / HTTP/1.1\r\n"
10846 "Host: www.example.com\r\n"
10847 "Connection: keep-alive\r\n"
10848 "Authorization: auth_token\r\n\r\n");
10849 const MockWrite kGetProxyAuth(
10850 "GET http://www.example.com/ HTTP/1.1\r\n"
10851 "Host: www.example.com\r\n"
10852 "Proxy-Connection: keep-alive\r\n"
10853 "Proxy-Authorization: auth_token\r\n\r\n");
10854 const MockWrite kGetAuthThroughProxy(
10855 "GET http://www.example.com/ HTTP/1.1\r\n"
10856 "Host: www.example.com\r\n"
10857 "Proxy-Connection: keep-alive\r\n"
10858 "Authorization: auth_token\r\n\r\n");
10859 const MockWrite kGetAuthWithProxyAuth(
10860 "GET http://www.example.com/ HTTP/1.1\r\n"
10861 "Host: www.example.com\r\n"
10862 "Proxy-Connection: keep-alive\r\n"
10863 "Proxy-Authorization: auth_token\r\n"
10864 "Authorization: auth_token\r\n\r\n");
10865 const MockWrite kConnect(
10866 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1710867 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1510868 "Proxy-Connection: keep-alive\r\n\r\n");
10869 const MockWrite kConnectProxyAuth(
10870 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1710871 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1510872 "Proxy-Connection: keep-alive\r\n"
10873 "Proxy-Authorization: auth_token\r\n\r\n");
10874
10875 const MockRead kSuccess(
10876 "HTTP/1.1 200 OK\r\n"
10877 "Content-Type: text/html; charset=iso-8859-1\r\n"
10878 "Content-Length: 3\r\n\r\n"
10879 "Yes");
10880 const MockRead kFailure(
10881 "Should not be called.");
10882 const MockRead kServerChallenge(
10883 "HTTP/1.1 401 Unauthorized\r\n"
10884 "WWW-Authenticate: Mock realm=server\r\n"
10885 "Content-Type: text/html; charset=iso-8859-1\r\n"
10886 "Content-Length: 14\r\n\r\n"
10887 "Unauthorized\r\n");
10888 const MockRead kProxyChallenge(
10889 "HTTP/1.1 407 Unauthorized\r\n"
10890 "Proxy-Authenticate: Mock realm=proxy\r\n"
10891 "Proxy-Connection: close\r\n"
10892 "Content-Type: text/html; charset=iso-8859-1\r\n"
10893 "Content-Length: 14\r\n\r\n"
10894 "Unauthorized\r\n");
10895 const MockRead kProxyConnected(
10896 "HTTP/1.1 200 Connection Established\r\n\r\n");
10897
10898 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
10899 // no constructors, but the C++ compiler on Windows warns about
10900 // unspecified data in compound literals. So, moved to using constructors,
10901 // and TestRound's created with the default constructor should not be used.
10902 struct TestRound {
10903 TestRound()
10904 : expected_rv(ERR_UNEXPECTED),
10905 extra_write(NULL),
10906 extra_read(NULL) {
10907 }
10908 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
10909 int expected_rv_arg)
10910 : write(write_arg),
10911 read(read_arg),
10912 expected_rv(expected_rv_arg),
10913 extra_write(NULL),
10914 extra_read(NULL) {
10915 }
10916 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
10917 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0110918 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1510919 : write(write_arg),
10920 read(read_arg),
10921 expected_rv(expected_rv_arg),
10922 extra_write(extra_write_arg),
10923 extra_read(extra_read_arg) {
10924 }
10925 MockWrite write;
10926 MockRead read;
10927 int expected_rv;
10928 const MockWrite* extra_write;
10929 const MockRead* extra_read;
10930 };
10931
10932 static const int kNoSSL = 500;
10933
10934 struct TestConfig {
thestig9d3bb0c2015-01-24 00:49:5110935 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1510936 AuthTiming proxy_auth_timing;
10937 int proxy_auth_rv;
thestig9d3bb0c2015-01-24 00:49:5110938 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1510939 AuthTiming server_auth_timing;
10940 int server_auth_rv;
10941 int num_auth_rounds;
10942 int first_ssl_round;
10943 TestRound rounds[3];
10944 } test_configs[] = {
10945 // Non-authenticating HTTP server with a direct connection.
10946 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
10947 { TestRound(kGet, kSuccess, OK)}},
10948 // Authenticating HTTP server with a direct connection.
10949 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
10950 { TestRound(kGet, kServerChallenge, OK),
10951 TestRound(kGetAuth, kSuccess, OK)}},
10952 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
10953 { TestRound(kGet, kServerChallenge, OK),
10954 TestRound(kGetAuth, kFailure, kAuthErr)}},
10955 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
10956 { TestRound(kGet, kServerChallenge, OK),
10957 TestRound(kGetAuth, kSuccess, OK)}},
10958 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
10959 { TestRound(kGet, kServerChallenge, OK),
10960 TestRound(kGetAuth, kFailure, kAuthErr)}},
10961 // Non-authenticating HTTP server through a non-authenticating proxy.
10962 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
10963 { TestRound(kGetProxy, kSuccess, OK)}},
10964 // Authenticating HTTP server through a non-authenticating proxy.
10965 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
10966 { TestRound(kGetProxy, kServerChallenge, OK),
10967 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
10968 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
10969 { TestRound(kGetProxy, kServerChallenge, OK),
10970 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
10971 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
10972 { TestRound(kGetProxy, kServerChallenge, OK),
10973 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
10974 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
10975 { TestRound(kGetProxy, kServerChallenge, OK),
10976 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
10977 // Non-authenticating HTTP server through an authenticating proxy.
10978 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
10979 { TestRound(kGetProxy, kProxyChallenge, OK),
10980 TestRound(kGetProxyAuth, kSuccess, OK)}},
10981 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
10982 { TestRound(kGetProxy, kProxyChallenge, OK),
10983 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
10984 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
10985 { TestRound(kGetProxy, kProxyChallenge, OK),
10986 TestRound(kGetProxyAuth, kSuccess, OK)}},
10987 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
10988 { TestRound(kGetProxy, kProxyChallenge, OK),
10989 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
10990 // Authenticating HTTP server through an authenticating proxy.
10991 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
10992 { TestRound(kGetProxy, kProxyChallenge, OK),
10993 TestRound(kGetProxyAuth, kServerChallenge, OK),
10994 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10995 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
10996 { TestRound(kGetProxy, kProxyChallenge, OK),
10997 TestRound(kGetProxyAuth, kServerChallenge, OK),
10998 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10999 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
11000 { TestRound(kGetProxy, kProxyChallenge, OK),
11001 TestRound(kGetProxyAuth, kServerChallenge, OK),
11002 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11003 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
11004 { TestRound(kGetProxy, kProxyChallenge, OK),
11005 TestRound(kGetProxyAuth, kServerChallenge, OK),
11006 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11007 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
11008 { TestRound(kGetProxy, kProxyChallenge, OK),
11009 TestRound(kGetProxyAuth, kServerChallenge, OK),
11010 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11011 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
11012 { TestRound(kGetProxy, kProxyChallenge, OK),
11013 TestRound(kGetProxyAuth, kServerChallenge, OK),
11014 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11015 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
11016 { TestRound(kGetProxy, kProxyChallenge, OK),
11017 TestRound(kGetProxyAuth, kServerChallenge, OK),
11018 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11019 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
11020 { TestRound(kGetProxy, kProxyChallenge, OK),
11021 TestRound(kGetProxyAuth, kServerChallenge, OK),
11022 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11023 // Non-authenticating HTTPS server with a direct connection.
11024 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
11025 { TestRound(kGet, kSuccess, OK)}},
11026 // Authenticating HTTPS server with a direct connection.
11027 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
11028 { TestRound(kGet, kServerChallenge, OK),
11029 TestRound(kGetAuth, kSuccess, OK)}},
11030 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
11031 { TestRound(kGet, kServerChallenge, OK),
11032 TestRound(kGetAuth, kFailure, kAuthErr)}},
11033 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
11034 { TestRound(kGet, kServerChallenge, OK),
11035 TestRound(kGetAuth, kSuccess, OK)}},
11036 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
11037 { TestRound(kGet, kServerChallenge, OK),
11038 TestRound(kGetAuth, kFailure, kAuthErr)}},
11039 // Non-authenticating HTTPS server with a non-authenticating proxy.
11040 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
11041 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
11042 // Authenticating HTTPS server through a non-authenticating proxy.
11043 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
11044 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11045 TestRound(kGetAuth, kSuccess, OK)}},
11046 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
11047 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11048 TestRound(kGetAuth, kFailure, kAuthErr)}},
11049 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
11050 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11051 TestRound(kGetAuth, kSuccess, OK)}},
11052 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
11053 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11054 TestRound(kGetAuth, kFailure, kAuthErr)}},
11055 // Non-Authenticating HTTPS server through an authenticating proxy.
11056 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
11057 { TestRound(kConnect, kProxyChallenge, OK),
11058 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
11059 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
11060 { TestRound(kConnect, kProxyChallenge, OK),
11061 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
11062 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
11063 { TestRound(kConnect, kProxyChallenge, OK),
11064 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
11065 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
11066 { TestRound(kConnect, kProxyChallenge, OK),
11067 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
11068 // Authenticating HTTPS server through an authenticating proxy.
11069 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11070 { TestRound(kConnect, kProxyChallenge, OK),
11071 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11072 &kGet, &kServerChallenge),
11073 TestRound(kGetAuth, kSuccess, OK)}},
11074 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11075 { TestRound(kConnect, kProxyChallenge, OK),
11076 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11077 &kGet, &kServerChallenge),
11078 TestRound(kGetAuth, kFailure, kAuthErr)}},
11079 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11080 { TestRound(kConnect, kProxyChallenge, OK),
11081 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11082 &kGet, &kServerChallenge),
11083 TestRound(kGetAuth, kSuccess, OK)}},
11084 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11085 { TestRound(kConnect, kProxyChallenge, OK),
11086 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11087 &kGet, &kServerChallenge),
11088 TestRound(kGetAuth, kFailure, kAuthErr)}},
11089 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11090 { TestRound(kConnect, kProxyChallenge, OK),
11091 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11092 &kGet, &kServerChallenge),
11093 TestRound(kGetAuth, kSuccess, OK)}},
11094 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11095 { TestRound(kConnect, kProxyChallenge, OK),
11096 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11097 &kGet, &kServerChallenge),
11098 TestRound(kGetAuth, kFailure, kAuthErr)}},
11099 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11100 { TestRound(kConnect, kProxyChallenge, OK),
11101 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11102 &kGet, &kServerChallenge),
11103 TestRound(kGetAuth, kSuccess, OK)}},
11104 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11105 { TestRound(kConnect, kProxyChallenge, OK),
11106 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11107 &kGet, &kServerChallenge),
11108 TestRound(kGetAuth, kFailure, kAuthErr)}},
11109 };
11110
viettrungluue4a8b882014-10-16 06:17:3811111 for (size_t i = 0; i < arraysize(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:0811112 HttpAuthHandlerMock::Factory* auth_factory(
11113 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711114 session_deps_.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:1511115 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:2611116
11117 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1511118 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:0811119 for (int n = 0; n < 2; n++) {
11120 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11121 std::string auth_challenge = "Mock realm=proxy";
11122 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2411123 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11124 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0811125 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
11126 origin, BoundNetLog());
11127 auth_handler->SetGenerateExpectation(
11128 test_config.proxy_auth_timing == AUTH_ASYNC,
11129 test_config.proxy_auth_rv);
11130 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
11131 }
[email protected]044de0642010-06-17 10:42:1511132 }
11133 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0011134 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1511135 std::string auth_challenge = "Mock realm=server";
11136 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2411137 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11138 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1511139 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
11140 origin, BoundNetLog());
11141 auth_handler->SetGenerateExpectation(
11142 test_config.server_auth_timing == AUTH_ASYNC,
11143 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:0811144 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1511145 }
11146 if (test_config.proxy_url) {
rdsmith82957ad2015-09-16 19:42:0311147 session_deps_.proxy_service =
11148 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:1511149 } else {
rdsmith82957ad2015-09-16 19:42:0311150 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1511151 }
11152
11153 HttpRequestInfo request;
11154 request.method = "GET";
11155 request.url = GURL(test_config.server_url);
11156 request.load_flags = 0;
11157
mmenkee65e7af2015-10-13 17:16:4211158 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
dcheng48459ac22014-08-26 00:46:4111159 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]044de0642010-06-17 10:42:1511160
rchcb68dc62015-05-21 04:45:3611161 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
11162
11163 std::vector<std::vector<MockRead>> mock_reads(1);
11164 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1511165 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11166 const TestRound& read_write_round = test_config.rounds[round];
11167
11168 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3611169 mock_reads.back().push_back(read_write_round.read);
11170 mock_writes.back().push_back(read_write_round.write);
11171
11172 // kProxyChallenge uses Proxy-Connection: close which means that the
11173 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5411174 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3611175 mock_reads.push_back(std::vector<MockRead>());
11176 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1511177 }
11178
rchcb68dc62015-05-21 04:45:3611179 if (read_write_round.extra_read) {
11180 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1511181 }
rchcb68dc62015-05-21 04:45:3611182 if (read_write_round.extra_write) {
11183 mock_writes.back().push_back(*read_write_round.extra_write);
11184 }
[email protected]044de0642010-06-17 10:42:1511185
11186 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1511187 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0711188 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1511189 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3611190 }
[email protected]044de0642010-06-17 10:42:1511191
rchcb68dc62015-05-21 04:45:3611192 ScopedVector<StaticSocketDataProvider> data_providers;
11193 for (size_t i = 0; i < mock_reads.size(); ++i) {
11194 data_providers.push_back(new StaticSocketDataProvider(
davidben5f8b6bc2015-11-25 03:19:5411195 mock_reads[i].data(), mock_reads[i].size(), mock_writes[i].data(),
11196 mock_writes[i].size()));
rchcb68dc62015-05-21 04:45:3611197 session_deps_.socket_factory->AddSocketDataProvider(
11198 data_providers.back());
11199 }
11200
11201 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11202 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1511203 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4111204 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1511205 int rv;
11206 if (round == 0) {
[email protected]49639fa2011-12-20 23:22:4111207 rv = trans.Start(&request, callback.callback(), BoundNetLog());
[email protected]044de0642010-06-17 10:42:1511208 } else {
[email protected]49639fa2011-12-20 23:22:4111209 rv = trans.RestartWithAuth(
11210 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1511211 }
11212 if (rv == ERR_IO_PENDING)
11213 rv = callback.WaitForResult();
11214
11215 // Compare results with expected data.
11216 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:5011217 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5511218 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1511219 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
11220 continue;
11221 }
11222 if (round + 1 < test_config.num_auth_rounds) {
11223 EXPECT_FALSE(response->auth_challenge.get() == NULL);
11224 } else {
11225 EXPECT_TRUE(response->auth_challenge.get() == NULL);
11226 }
11227 }
[email protected]e5ae96a2010-04-14 20:12:4511228 }
11229}
11230
[email protected]23e482282013-06-14 16:08:0211231TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1411232 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1411233 HttpAuthHandlerMock::Factory* auth_factory(
11234 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711235 session_deps_.http_auth_handler_factory.reset(auth_factory);
rdsmith82957ad2015-09-16 19:42:0311236 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0711237 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
11238 session_deps_.host_resolver->set_synchronous_mode(true);
[email protected]c871bce92010-07-15 21:51:1411239
11240 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11241 auth_handler->set_connection_based(true);
11242 std::string auth_challenge = "Mock realm=server";
11243 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2411244 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11245 auth_challenge.end());
[email protected]c871bce92010-07-15 21:51:1411246 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
11247 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:0811248 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1411249
[email protected]c871bce92010-07-15 21:51:1411250 int rv = OK;
11251 const HttpResponseInfo* response = NULL;
11252 HttpRequestInfo request;
11253 request.method = "GET";
11254 request.url = origin;
11255 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:2711256
mmenkee65e7af2015-10-13 17:16:4211257 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1011258
11259 // Use a TCP Socket Pool with only one connection per group. This is used
11260 // to validate that the TCP socket is not released to the pool between
11261 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4211262 HttpNetworkSessionPeer session_peer(session.get());
[email protected]ab739042011-04-07 15:22:2811263 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:1011264 50, // Max sockets for pool
11265 1, // Max sockets per group
[email protected]bb88e1d32013-05-03 23:11:0711266 session_deps_.host_resolver.get(),
11267 session_deps_.socket_factory.get(),
11268 session_deps_.net_log);
[email protected]831e4a32013-11-14 02:14:4411269 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
11270 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:0211271 mock_pool_manager->SetTransportSocketPool(transport_pool);
dchenge3d1ddc2014-10-15 19:30:5111272 session_peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
[email protected]7ef4cbbb2011-02-06 11:19:1011273
[email protected]262eec82013-03-19 21:01:3611274 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011275 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111276 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1411277
11278 const MockWrite kGet(
11279 "GET / HTTP/1.1\r\n"
11280 "Host: www.example.com\r\n"
11281 "Connection: keep-alive\r\n\r\n");
11282 const MockWrite kGetAuth(
11283 "GET / HTTP/1.1\r\n"
11284 "Host: www.example.com\r\n"
11285 "Connection: keep-alive\r\n"
11286 "Authorization: auth_token\r\n\r\n");
11287
11288 const MockRead kServerChallenge(
11289 "HTTP/1.1 401 Unauthorized\r\n"
11290 "WWW-Authenticate: Mock realm=server\r\n"
11291 "Content-Type: text/html; charset=iso-8859-1\r\n"
11292 "Content-Length: 14\r\n\r\n"
11293 "Unauthorized\r\n");
11294 const MockRead kSuccess(
11295 "HTTP/1.1 200 OK\r\n"
11296 "Content-Type: text/html; charset=iso-8859-1\r\n"
11297 "Content-Length: 3\r\n\r\n"
11298 "Yes");
11299
11300 MockWrite writes[] = {
11301 // First round
11302 kGet,
11303 // Second round
11304 kGetAuth,
11305 // Third round
11306 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3011307 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1011308 kGetAuth,
11309 // Competing request
11310 kGet,
[email protected]c871bce92010-07-15 21:51:1411311 };
11312 MockRead reads[] = {
11313 // First round
11314 kServerChallenge,
11315 // Second round
11316 kServerChallenge,
11317 // Third round
[email protected]eca50e122010-09-11 14:03:3011318 kServerChallenge,
11319 // Fourth round
[email protected]c871bce92010-07-15 21:51:1411320 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1011321 // Competing response
11322 kSuccess,
[email protected]c871bce92010-07-15 21:51:1411323 };
11324 StaticSocketDataProvider data_provider(reads, arraysize(reads),
11325 writes, arraysize(writes));
[email protected]bb88e1d32013-05-03 23:11:0711326 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1411327
thestig9d3bb0c2015-01-24 00:49:5111328 const char kSocketGroup[] = "www.example.com:80";
[email protected]7ef4cbbb2011-02-06 11:19:1011329
11330 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1411331 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111332 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]c871bce92010-07-15 21:51:1411333 if (rv == ERR_IO_PENDING)
11334 rv = callback.WaitForResult();
11335 EXPECT_EQ(OK, rv);
11336 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011337 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411338 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811339 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411340
[email protected]7ef4cbbb2011-02-06 11:19:1011341 // In between rounds, another request comes in for the same domain.
11342 // It should not be able to grab the TCP socket that trans has already
11343 // claimed.
11344 scoped_ptr<HttpTransaction> trans_compete(
[email protected]90499482013-06-01 00:39:5011345 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111346 TestCompletionCallback callback_compete;
11347 rv = trans_compete->Start(
11348 &request, callback_compete.callback(), BoundNetLog());
[email protected]7ef4cbbb2011-02-06 11:19:1011349 EXPECT_EQ(ERR_IO_PENDING, rv);
11350 // callback_compete.WaitForResult at this point would stall forever,
11351 // since the HttpNetworkTransaction does not release the request back to
11352 // the pool until after authentication completes.
11353
11354 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1411355 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111356 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411357 if (rv == ERR_IO_PENDING)
11358 rv = callback.WaitForResult();
11359 EXPECT_EQ(OK, rv);
11360 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011361 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411362 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811363 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411364
[email protected]7ef4cbbb2011-02-06 11:19:1011365 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1411366 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111367 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411368 if (rv == ERR_IO_PENDING)
11369 rv = callback.WaitForResult();
11370 EXPECT_EQ(OK, rv);
11371 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011372 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411373 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811374 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:3011375
[email protected]7ef4cbbb2011-02-06 11:19:1011376 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3011377 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111378 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3011379 if (rv == ERR_IO_PENDING)
11380 rv = callback.WaitForResult();
11381 EXPECT_EQ(OK, rv);
11382 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011383 ASSERT_TRUE(response != NULL);
[email protected]eca50e122010-09-11 14:03:3011384 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811385 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011386
11387 // Read the body since the fourth round was successful. This will also
11388 // release the socket back to the pool.
11389 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
[email protected]90499482013-06-01 00:39:5011390 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011391 if (rv == ERR_IO_PENDING)
11392 rv = callback.WaitForResult();
11393 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011394 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011395 EXPECT_EQ(0, rv);
11396 // There are still 0 idle sockets, since the trans_compete transaction
11397 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:2811398 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011399
11400 // The competing request can now finish. Wait for the headers and then
11401 // read the body.
11402 rv = callback_compete.WaitForResult();
11403 EXPECT_EQ(OK, rv);
[email protected]90499482013-06-01 00:39:5011404 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011405 if (rv == ERR_IO_PENDING)
11406 rv = callback.WaitForResult();
11407 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011408 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011409 EXPECT_EQ(0, rv);
11410
11411 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:2811412 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411413}
11414
[email protected]65041fa2010-05-21 06:56:5311415// This tests the case that a request is issued via http instead of spdy after
11416// npn is negotiated.
[email protected]23e482282013-06-14 16:08:0211417TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
bnc55ff9da2015-08-19 18:42:3511418 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311419 NextProtoVector next_protos;
[email protected]0ce3af82013-07-22 16:17:1611420 next_protos.push_back(kProtoHTTP11);
[email protected]d7599122014-05-24 03:37:2311421 session_deps_.next_protos = next_protos;
11422
[email protected]65041fa2010-05-21 06:56:5311423 HttpRequestInfo request;
11424 request.method = "GET";
bncce36dca22015-04-21 22:11:2311425 request.url = GURL("https://www.example.org/");
[email protected]65041fa2010-05-21 06:56:5311426 request.load_flags = 0;
11427
11428 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311429 MockWrite(
11430 "GET / HTTP/1.1\r\n"
11431 "Host: www.example.org\r\n"
11432 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5311433 };
11434
[email protected]8a0fc822013-06-27 20:52:4311435 std::string alternate_protocol_http_header =
11436 GetAlternateProtocolHttpHeader();
11437
[email protected]65041fa2010-05-21 06:56:5311438 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211439 MockRead("HTTP/1.1 200 OK\r\n"),
11440 MockRead(alternate_protocol_http_header.c_str()),
11441 MockRead("\r\n"),
11442 MockRead("hello world"),
11443 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5311444 };
11445
[email protected]8ddf8322012-02-23 18:08:0611446 SSLSocketDataProvider ssl(ASYNC, OK);
davidben6974bf72015-04-27 17:52:4811447 ssl.SetNextProto(kProtoHTTP11);
[email protected]65041fa2010-05-21 06:56:5311448
[email protected]bb88e1d32013-05-03 23:11:0711449 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5311450
11451 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11452 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0711453 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5311454
[email protected]49639fa2011-12-20 23:22:4111455 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5311456
mmenkee65e7af2015-10-13 17:16:4211457 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3611458 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011459 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]65041fa2010-05-21 06:56:5311460
[email protected]49639fa2011-12-20 23:22:4111461 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]65041fa2010-05-21 06:56:5311462
11463 EXPECT_EQ(ERR_IO_PENDING, rv);
11464 EXPECT_EQ(OK, callback.WaitForResult());
11465
11466 const HttpResponseInfo* response = trans->GetResponseInfo();
11467 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011468 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]65041fa2010-05-21 06:56:5311469 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11470
11471 std::string response_data;
11472 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11473 EXPECT_EQ("hello world", response_data);
11474
11475 EXPECT_FALSE(response->was_fetched_via_spdy);
11476 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]65041fa2010-05-21 06:56:5311477}
[email protected]26ef6582010-06-24 02:30:4711478
bnc55ff9da2015-08-19 18:42:3511479// Simulate the SSL handshake completing with an NPN negotiation followed by an
11480// immediate server closing of the socket.
11481// Regression test for https://crbug.com/46369.
[email protected]23e482282013-06-14 16:08:0211482TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
bnc55ff9da2015-08-19 18:42:3511483 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311484 session_deps_.next_protos = SpdyNextProtos();
[email protected]26ef6582010-06-24 02:30:4711485
11486 HttpRequestInfo request;
11487 request.method = "GET";
bncce36dca22015-04-21 22:11:2311488 request.url = GURL("https://www.example.org/");
[email protected]26ef6582010-06-24 02:30:4711489 request.load_flags = 0;
11490
[email protected]8ddf8322012-02-23 18:08:0611491 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811492 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0711493 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4711494
[email protected]cdf8f7e72013-05-23 10:56:4611495 scoped_ptr<SpdyFrame> req(
11496 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1311497 MockWrite spdy_writes[] = {CreateMockWrite(*req, 1)};
[email protected]26ef6582010-06-24 02:30:4711498
11499 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0611500 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4711501 };
11502
rch8e6c6c42015-05-01 14:05:1311503 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11504 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711505 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4711506
[email protected]49639fa2011-12-20 23:22:4111507 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4711508
mmenkee65e7af2015-10-13 17:16:4211509 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3611510 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011511 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]26ef6582010-06-24 02:30:4711512
[email protected]49639fa2011-12-20 23:22:4111513 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]26ef6582010-06-24 02:30:4711514 EXPECT_EQ(ERR_IO_PENDING, rv);
11515 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
[email protected]26ef6582010-06-24 02:30:4711516}
[email protected]65d34382010-07-01 18:12:2611517
[email protected]795cbf82013-07-22 09:37:2711518// A subclass of HttpAuthHandlerMock that records the request URL when
11519// it gets it. This is needed since the auth handler may get destroyed
11520// before we get a chance to query it.
11521class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
11522 public:
11523 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
11524
dchengb03027d2014-10-21 12:00:2011525 ~UrlRecordingHttpAuthHandlerMock() override {}
[email protected]795cbf82013-07-22 09:37:2711526
11527 protected:
dchengb03027d2014-10-21 12:00:2011528 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
11529 const HttpRequestInfo* request,
11530 const CompletionCallback& callback,
11531 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2711532 *url_ = request->url;
11533 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
11534 credentials, request, callback, auth_token);
11535 }
11536
11537 private:
11538 GURL* url_;
11539};
11540
bnc55ff9da2015-08-19 18:42:3511541// This test ensures that the URL passed into the proxy is upgraded to https
11542// when doing an Alternate Protocol upgrade.
[email protected]23e482282013-06-14 16:08:0211543TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
bnc55ff9da2015-08-19 18:42:3511544 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311545 session_deps_.next_protos = SpdyNextProtos();
[email protected]f45c1ee2010-08-03 00:54:3011546
rdsmith82957ad2015-09-16 19:42:0311547 session_deps_.proxy_service =
11548 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5111549 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711550 session_deps_.net_log = &net_log;
[email protected]795cbf82013-07-22 09:37:2711551 GURL request_url;
11552 {
11553 HttpAuthHandlerMock::Factory* auth_factory =
11554 new HttpAuthHandlerMock::Factory();
11555 UrlRecordingHttpAuthHandlerMock* auth_handler =
11556 new UrlRecordingHttpAuthHandlerMock(&request_url);
11557 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
11558 auth_factory->set_do_init_from_challenge(true);
11559 session_deps_.http_auth_handler_factory.reset(auth_factory);
11560 }
[email protected]f45c1ee2010-08-03 00:54:3011561
11562 HttpRequestInfo request;
11563 request.method = "GET";
bncce36dca22015-04-21 22:11:2311564 request.url = GURL("http://www.example.org");
[email protected]f45c1ee2010-08-03 00:54:3011565 request.load_flags = 0;
11566
11567 // First round goes unauthenticated through the proxy.
11568 MockWrite data_writes_1[] = {
bncce36dca22015-04-21 22:11:2311569 MockWrite(
11570 "GET http://www.example.org/ HTTP/1.1\r\n"
11571 "Host: www.example.org\r\n"
11572 "Proxy-Connection: keep-alive\r\n"
11573 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011574 };
11575 MockRead data_reads_1[] = {
[email protected]8ddf8322012-02-23 18:08:0611576 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
bnc33b8cef42014-11-19 17:30:3811577 MockRead("HTTP/1.1 200 OK\r\n"),
11578 MockRead("Alternate-Protocol: 443:"),
11579 MockRead(GetAlternateProtocolFromParam()),
11580 MockRead("\r\n"),
11581 MockRead("Proxy-Connection: close\r\n"),
11582 MockRead("\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011583 };
11584 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
11585 data_writes_1, arraysize(data_writes_1));
11586
bncce36dca22015-04-21 22:11:2311587 // Second round tries to tunnel to www.example.org due to the
[email protected]f45c1ee2010-08-03 00:54:3011588 // Alternate-Protocol announcement in the first round. It fails due
11589 // to a proxy authentication challenge.
bncce36dca22015-04-21 22:11:2311590 // After the failure, a tunnel is established to www.example.org using
[email protected]394816e92010-08-03 07:38:5911591 // Proxy-Authorization headers. There is then a SPDY request round.
11592 //
[email protected]fe3b7dc2012-02-03 19:52:0911593 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
11594 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
11595 // does a Disconnect and Connect on the same socket, rather than trying
11596 // to obtain a new one.
11597 //
[email protected]394816e92010-08-03 07:38:5911598 // NOTE: Originally, the proxy response to the second CONNECT request
11599 // simply returned another 407 so the unit test could skip the SSL connection
11600 // establishment and SPDY framing issues. Alas, the
11601 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:3011602 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:5911603
[email protected]cdf8f7e72013-05-23 10:56:4611604 scoped_ptr<SpdyFrame> req(
11605 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]23e482282013-06-14 16:08:0211606 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11607 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]f45c1ee2010-08-03 00:54:3011608
[email protected]394816e92010-08-03 07:38:5911609 MockWrite data_writes_2[] = {
bncce36dca22015-04-21 22:11:2311610 // First connection attempt without Proxy-Authorization.
rch8e6c6c42015-05-01 14:05:1311611 MockWrite(ASYNC, 0,
11612 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711613 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1311614 "Proxy-Connection: keep-alive\r\n"
11615 "\r\n"),
[email protected]394816e92010-08-03 07:38:5911616
bncce36dca22015-04-21 22:11:2311617 // Second connection attempt with Proxy-Authorization.
rch8e6c6c42015-05-01 14:05:1311618 MockWrite(ASYNC, 2,
11619 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711620 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1311621 "Proxy-Connection: keep-alive\r\n"
11622 "Proxy-Authorization: auth_token\r\n"
11623 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011624
bncce36dca22015-04-21 22:11:2311625 // SPDY request
rch8e6c6c42015-05-01 14:05:1311626 CreateMockWrite(*req, 4),
[email protected]f45c1ee2010-08-03 00:54:3011627 };
[email protected]394816e92010-08-03 07:38:5911628 MockRead data_reads_2[] = {
rch8e6c6c42015-05-01 14:05:1311629 // First connection attempt fails
mmenkee71e15332015-10-07 16:39:5411630 MockRead(ASYNC, 1,
11631 "HTTP/1.1 407 Unauthorized\r\n"
11632 "Proxy-Authenticate: Mock\r\n"
11633 "Content-Length: 0\r\n"
11634 "Proxy-Connection: keep-alive\r\n"
11635 "\r\n"),
[email protected]394816e92010-08-03 07:38:5911636
rch8e6c6c42015-05-01 14:05:1311637 // Second connection attempt passes
mmenkee71e15332015-10-07 16:39:5411638 MockRead(ASYNC, 3, "HTTP/1.1 200 Connected\r\n\r\n"),
[email protected]394816e92010-08-03 07:38:5911639
rch8e6c6c42015-05-01 14:05:1311640 // SPDY response
mmenkee71e15332015-10-07 16:39:5411641 CreateMockRead(*resp.get(), 5), CreateMockRead(*data.get(), 6),
rch8e6c6c42015-05-01 14:05:1311642 MockRead(ASYNC, 0, 0, 7),
[email protected]394816e92010-08-03 07:38:5911643 };
rch8e6c6c42015-05-01 14:05:1311644 SequencedSocketData data_2(data_reads_2, arraysize(data_reads_2),
11645 data_writes_2, arraysize(data_writes_2));
[email protected]f45c1ee2010-08-03 00:54:3011646
[email protected]8ddf8322012-02-23 18:08:0611647 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811648 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2311649 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11650 ASSERT_TRUE(ssl.cert.get());
[email protected]f45c1ee2010-08-03 00:54:3011651
[email protected]d973e99a2012-02-17 21:02:3611652 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5511653 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
11654 NULL, 0, NULL, 0);
11655 hanging_non_alternate_protocol_socket.set_connect_data(
11656 never_finishing_connect);
11657
[email protected]bb88e1d32013-05-03 23:11:0711658 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
11659 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
11660 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11661 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5511662 &hanging_non_alternate_protocol_socket);
mmenkee65e7af2015-10-13 17:16:4211663 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f45c1ee2010-08-03 00:54:3011664
11665 // First round should work and provide the Alternate-Protocol state.
[email protected]49639fa2011-12-20 23:22:4111666 TestCompletionCallback callback_1;
[email protected]262eec82013-03-19 21:01:3611667 scoped_ptr<HttpTransaction> trans_1(
[email protected]90499482013-06-01 00:39:5011668 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111669 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:3011670 EXPECT_EQ(ERR_IO_PENDING, rv);
11671 EXPECT_EQ(OK, callback_1.WaitForResult());
11672
11673 // Second round should attempt a tunnel connect and get an auth challenge.
[email protected]49639fa2011-12-20 23:22:4111674 TestCompletionCallback callback_2;
[email protected]262eec82013-03-19 21:01:3611675 scoped_ptr<HttpTransaction> trans_2(
[email protected]90499482013-06-01 00:39:5011676 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111677 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:3011678 EXPECT_EQ(ERR_IO_PENDING, rv);
11679 EXPECT_EQ(OK, callback_2.WaitForResult());
11680 const HttpResponseInfo* response = trans_2->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011681 ASSERT_TRUE(response != NULL);
[email protected]f45c1ee2010-08-03 00:54:3011682 ASSERT_FALSE(response->auth_challenge.get() == NULL);
11683
11684 // Restart with auth. Tunnel should work and response received.
[email protected]49639fa2011-12-20 23:22:4111685 TestCompletionCallback callback_3;
11686 rv = trans_2->RestartWithAuth(
11687 AuthCredentials(kFoo, kBar), callback_3.callback());
[email protected]f45c1ee2010-08-03 00:54:3011688 EXPECT_EQ(ERR_IO_PENDING, rv);
11689 EXPECT_EQ(OK, callback_3.WaitForResult());
11690
11691 // After all that work, these two lines (or actually, just the scheme) are
11692 // what this test is all about. Make sure it happens correctly.
[email protected]f45c1ee2010-08-03 00:54:3011693 EXPECT_EQ("https", request_url.scheme());
bncce36dca22015-04-21 22:11:2311694 EXPECT_EQ("www.example.org", request_url.host());
[email protected]f45c1ee2010-08-03 00:54:3011695
[email protected]029c83b62013-01-24 05:28:2011696 LoadTimingInfo load_timing_info;
11697 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
11698 TestLoadTimingNotReusedWithPac(load_timing_info,
11699 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]8e6441ca2010-08-19 05:56:3811700}
11701
11702// Test that if we cancel the transaction as the connection is completing, that
11703// everything tears down correctly.
[email protected]23e482282013-06-14 16:08:0211704TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3811705 // Setup everything about the connection to complete synchronously, so that
11706 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
11707 // for is the callback from the HttpStreamRequest.
11708 // Then cancel the transaction.
11709 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3611710 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3811711 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0611712 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
11713 MockRead(SYNCHRONOUS, "hello world"),
11714 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3811715 };
11716
[email protected]8e6441ca2010-08-19 05:56:3811717 HttpRequestInfo request;
11718 request.method = "GET";
bncce36dca22015-04-21 22:11:2311719 request.url = GURL("http://www.example.org/");
[email protected]8e6441ca2010-08-19 05:56:3811720 request.load_flags = 0;
11721
[email protected]bb88e1d32013-05-03 23:11:0711722 session_deps_.host_resolver->set_synchronous_mode(true);
mmenkee65e7af2015-10-13 17:16:4211723 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:2711724 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4111725 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:2711726
[email protected]8e6441ca2010-08-19 05:56:3811727 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
11728 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0711729 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3811730
[email protected]49639fa2011-12-20 23:22:4111731 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3811732
vishal.b62985ca92015-04-17 08:45:5111733 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4111734 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]8e6441ca2010-08-19 05:56:3811735 EXPECT_EQ(ERR_IO_PENDING, rv);
11736 trans.reset(); // Cancel the transaction here.
11737
[email protected]2da659e2013-05-23 20:51:3411738 base::MessageLoop::current()->RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3011739}
11740
[email protected]ecab6e052014-05-16 14:58:1211741// Test that if a transaction is cancelled after receiving the headers, the
11742// stream is drained properly and added back to the socket pool. The main
11743// purpose of this test is to make sure that an HttpStreamParser can be read
11744// from after the HttpNetworkTransaction and the objects it owns have been
11745// deleted.
11746// See http://crbug.com/368418
11747TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
11748 MockRead data_reads[] = {
11749 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
11750 MockRead(ASYNC, "Content-Length: 2\r\n"),
11751 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
11752 MockRead(ASYNC, "1"),
11753 // 2 async reads are necessary to trigger a ReadResponseBody call after the
11754 // HttpNetworkTransaction has been deleted.
11755 MockRead(ASYNC, "2"),
11756 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
11757 };
11758 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
11759 session_deps_.socket_factory->AddSocketDataProvider(&data);
11760
mmenkee65e7af2015-10-13 17:16:4211761 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1211762
11763 {
11764 HttpRequestInfo request;
11765 request.method = "GET";
bncce36dca22015-04-21 22:11:2311766 request.url = GURL("http://www.example.org/");
[email protected]ecab6e052014-05-16 14:58:1211767 request.load_flags = 0;
11768
dcheng48459ac22014-08-26 00:46:4111769 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1211770 TestCompletionCallback callback;
11771
11772 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
11773 EXPECT_EQ(ERR_IO_PENDING, rv);
11774 callback.WaitForResult();
11775
11776 const HttpResponseInfo* response = trans.GetResponseInfo();
11777 ASSERT_TRUE(response != NULL);
11778 EXPECT_TRUE(response->headers.get() != NULL);
11779 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11780
11781 // The transaction and HttpRequestInfo are deleted.
11782 }
11783
11784 // Let the HttpResponseBodyDrainer drain the socket.
11785 base::MessageLoop::current()->RunUntilIdle();
11786
11787 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4111788 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1211789}
11790
[email protected]76a505b2010-08-25 06:23:0011791// Test a basic GET request through a proxy.
[email protected]23e482282013-06-14 16:08:0211792TEST_P(HttpNetworkTransactionTest, ProxyGet) {
rdsmith82957ad2015-09-16 19:42:0311793 session_deps_.proxy_service =
11794 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5111795 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711796 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4211797 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0011798
[email protected]76a505b2010-08-25 06:23:0011799 HttpRequestInfo request;
11800 request.method = "GET";
bncce36dca22015-04-21 22:11:2311801 request.url = GURL("http://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0011802
11803 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311804 MockWrite(
11805 "GET http://www.example.org/ HTTP/1.1\r\n"
11806 "Host: www.example.org\r\n"
11807 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0011808 };
11809
11810 MockRead data_reads1[] = {
11811 MockRead("HTTP/1.1 200 OK\r\n"),
11812 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11813 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611814 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0011815 };
11816
11817 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
11818 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0711819 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0011820
[email protected]49639fa2011-12-20 23:22:4111821 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0011822
[email protected]262eec82013-03-19 21:01:3611823 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011824 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]597a1ab2014-06-26 08:12:2711825 BeforeProxyHeadersSentHandler proxy_headers_handler;
11826 trans->SetBeforeProxyHeadersSentCallback(
11827 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
11828 base::Unretained(&proxy_headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5011829
[email protected]49639fa2011-12-20 23:22:4111830 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0011831 EXPECT_EQ(ERR_IO_PENDING, rv);
11832
11833 rv = callback1.WaitForResult();
11834 EXPECT_EQ(OK, rv);
11835
11836 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011837 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:0011838
11839 EXPECT_TRUE(response->headers->IsKeepAlive());
11840 EXPECT_EQ(200, response->headers->response_code());
11841 EXPECT_EQ(100, response->headers->GetContentLength());
11842 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1511843 EXPECT_TRUE(
11844 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
[email protected]597a1ab2014-06-26 08:12:2711845 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
11846 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0011847 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2011848
11849 LoadTimingInfo load_timing_info;
11850 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11851 TestLoadTimingNotReusedWithPac(load_timing_info,
11852 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0011853}
11854
11855// Test a basic HTTPS GET request through a proxy.
[email protected]23e482282013-06-14 16:08:0211856TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
rdsmith82957ad2015-09-16 19:42:0311857 session_deps_.proxy_service =
11858 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5111859 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711860 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4211861 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0011862
[email protected]76a505b2010-08-25 06:23:0011863 HttpRequestInfo request;
11864 request.method = "GET";
bncce36dca22015-04-21 22:11:2311865 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0011866
11867 // Since we have proxy, should try to establish tunnel.
11868 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1711869 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
11870 "Host: www.example.org:443\r\n"
11871 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0011872
rsleevidb16bb02015-11-12 23:47:1711873 MockWrite("GET / HTTP/1.1\r\n"
11874 "Host: www.example.org\r\n"
11875 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0011876 };
11877
11878 MockRead data_reads1[] = {
11879 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11880
11881 MockRead("HTTP/1.1 200 OK\r\n"),
11882 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11883 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611884 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0011885 };
11886
11887 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
11888 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0711889 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0611890 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711891 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0011892
[email protected]49639fa2011-12-20 23:22:4111893 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0011894
[email protected]262eec82013-03-19 21:01:3611895 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011896 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:5011897
[email protected]49639fa2011-12-20 23:22:4111898 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0011899 EXPECT_EQ(ERR_IO_PENDING, rv);
11900
11901 rv = callback1.WaitForResult();
11902 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:4611903 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4011904 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0011905 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4011906 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0011907 NetLog::PHASE_NONE);
11908 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4011909 entries, pos,
[email protected]76a505b2010-08-25 06:23:0011910 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11911 NetLog::PHASE_NONE);
11912
11913 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011914 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:0011915
11916 EXPECT_TRUE(response->headers->IsKeepAlive());
11917 EXPECT_EQ(200, response->headers->response_code());
11918 EXPECT_EQ(100, response->headers->GetContentLength());
11919 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11920 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1511921 EXPECT_TRUE(
11922 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
[email protected]029c83b62013-01-24 05:28:2011923
11924 LoadTimingInfo load_timing_info;
11925 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11926 TestLoadTimingNotReusedWithPac(load_timing_info,
11927 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0011928}
11929
rsleevidb16bb02015-11-12 23:47:1711930// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
11931// literal host.
11932TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
11933 session_deps_.proxy_service =
11934 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
11935 BoundTestNetLog log;
11936 session_deps_.net_log = log.bound().net_log();
11937 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11938
11939 HttpRequestInfo request;
11940 request.method = "GET";
11941 request.url = GURL("https://[::1]:443/");
11942
11943 // Since we have proxy, should try to establish tunnel.
11944 MockWrite data_writes1[] = {
11945 MockWrite("CONNECT [::1]:443 HTTP/1.1\r\n"
11946 "Host: [::1]:443\r\n"
11947 "Proxy-Connection: keep-alive\r\n\r\n"),
11948
11949 MockWrite("GET / HTTP/1.1\r\n"
11950 "Host: [::1]\r\n"
11951 "Connection: keep-alive\r\n\r\n"),
11952 };
11953
11954 MockRead data_reads1[] = {
11955 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11956
11957 MockRead("HTTP/1.1 200 OK\r\n"),
11958 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11959 MockRead("Content-Length: 100\r\n\r\n"),
11960 MockRead(SYNCHRONOUS, OK),
11961 };
11962
11963 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
11964 data_writes1, arraysize(data_writes1));
11965 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11966 SSLSocketDataProvider ssl(ASYNC, OK);
11967 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11968
11969 TestCompletionCallback callback1;
11970
11971 scoped_ptr<HttpTransaction> trans(
11972 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11973
11974 int rv = trans->Start(&request, callback1.callback(), log.bound());
11975 EXPECT_EQ(ERR_IO_PENDING, rv);
11976
11977 rv = callback1.WaitForResult();
11978 EXPECT_EQ(OK, rv);
11979 TestNetLogEntry::List entries;
11980 log.GetEntries(&entries);
11981 size_t pos = ExpectLogContainsSomewhere(
11982 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
11983 NetLog::PHASE_NONE);
11984 ExpectLogContainsSomewhere(
11985 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11986 NetLog::PHASE_NONE);
11987
11988 const HttpResponseInfo* response = trans->GetResponseInfo();
11989 ASSERT_TRUE(response != NULL);
11990
11991 EXPECT_TRUE(response->headers->IsKeepAlive());
11992 EXPECT_EQ(200, response->headers->response_code());
11993 EXPECT_EQ(100, response->headers->GetContentLength());
11994 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11995 EXPECT_TRUE(response->was_fetched_via_proxy);
11996 EXPECT_TRUE(
11997 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
11998
11999 LoadTimingInfo load_timing_info;
12000 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12001 TestLoadTimingNotReusedWithPac(load_timing_info,
12002 CONNECT_TIMING_HAS_SSL_TIMES);
12003}
12004
[email protected]76a505b2010-08-25 06:23:0012005// Test a basic HTTPS GET request through a proxy, but the server hangs up
12006// while establishing the tunnel.
[email protected]23e482282013-06-14 16:08:0212007TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
rdsmith82957ad2015-09-16 19:42:0312008 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112009 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712010 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4212011 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012012
[email protected]76a505b2010-08-25 06:23:0012013 HttpRequestInfo request;
12014 request.method = "GET";
bncce36dca22015-04-21 22:11:2312015 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012016
12017 // Since we have proxy, should try to establish tunnel.
12018 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1712019 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
12020 "Host: www.example.org:443\r\n"
12021 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012022
rsleevidb16bb02015-11-12 23:47:1712023 MockWrite("GET / HTTP/1.1\r\n"
12024 "Host: www.example.org\r\n"
12025 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012026 };
12027
12028 MockRead data_reads1[] = {
[email protected]8ddf8322012-02-23 18:08:0612029 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]76a505b2010-08-25 06:23:0012030 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612031 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0012032 };
12033
12034 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12035 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712036 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0612037 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712038 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0012039
[email protected]49639fa2011-12-20 23:22:4112040 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012041
[email protected]262eec82013-03-19 21:01:3612042 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012043 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:5012044
[email protected]49639fa2011-12-20 23:22:4112045 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0012046 EXPECT_EQ(ERR_IO_PENDING, rv);
12047
12048 rv = callback1.WaitForResult();
12049 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
mmenke43758e62015-05-04 21:09:4612050 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4012051 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0012052 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012053 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0012054 NetLog::PHASE_NONE);
12055 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012056 entries, pos,
[email protected]76a505b2010-08-25 06:23:0012057 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12058 NetLog::PHASE_NONE);
12059}
12060
[email protected]749eefa82010-09-13 22:14:0312061// Test for crbug.com/55424.
[email protected]23e482282013-06-14 16:08:0212062TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
[email protected]cdf8f7e72013-05-23 10:56:4612063 scoped_ptr<SpdyFrame> req(
bncce36dca22015-04-21 22:11:2312064 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rch8e6c6c42015-05-01 14:05:1312065 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]749eefa82010-09-13 22:14:0312066
[email protected]23e482282013-06-14 16:08:0212067 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12068 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0312069 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312070 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0312071 };
12072
rch8e6c6c42015-05-01 14:05:1312073 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
12074 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712075 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0312076
[email protected]8ddf8322012-02-23 18:08:0612077 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812078 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712079 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0312080
mmenkee65e7af2015-10-13 17:16:4212081 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0312082
12083 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2312084 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4012085 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5312086 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2712087 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:4212088 CreateInsecureSpdySession(session.get(), key, BoundNetLog());
[email protected]749eefa82010-09-13 22:14:0312089
12090 HttpRequestInfo request;
12091 request.method = "GET";
bncce36dca22015-04-21 22:11:2312092 request.url = GURL("https://www.example.org/");
[email protected]749eefa82010-09-13 22:14:0312093 request.load_flags = 0;
12094
12095 // This is the important line that marks this as a preconnect.
12096 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
12097
[email protected]262eec82013-03-19 21:01:3612098 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012099 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]749eefa82010-09-13 22:14:0312100
[email protected]41d64e82013-07-03 22:44:2612101 TestCompletionCallback callback;
[email protected]49639fa2011-12-20 23:22:4112102 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]749eefa82010-09-13 22:14:0312103 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112104 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]749eefa82010-09-13 22:14:0312105}
12106
[email protected]73b8dd222010-11-11 19:55:2412107// Given a net error, cause that error to be returned from the first Write()
12108// call and verify that the HttpTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0212109void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0712110 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2912111 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712112 request_info.url = GURL("https://www.example.com/");
12113 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912114 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712115
[email protected]8ddf8322012-02-23 18:08:0612116 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2912117 MockWrite data_writes[] = {
12118 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2412119 };
ttuttle859dc7a2015-04-23 19:42:2912120 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0712121 session_deps_.socket_factory->AddSocketDataProvider(&data);
12122 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2412123
mmenkee65e7af2015-10-13 17:16:4212124 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612125 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012126 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]73b8dd222010-11-11 19:55:2412127
[email protected]49639fa2011-12-20 23:22:4112128 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912129 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12130 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2412131 rv = callback.WaitForResult();
12132 ASSERT_EQ(error, rv);
12133}
12134
[email protected]23e482282013-06-14 16:08:0212135TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2412136 // Just check a grab bag of cert errors.
12137 static const int kErrors[] = {
12138 ERR_CERT_COMMON_NAME_INVALID,
12139 ERR_CERT_AUTHORITY_INVALID,
12140 ERR_CERT_DATE_INVALID,
12141 };
12142 for (size_t i = 0; i < arraysize(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0612143 CheckErrorIsPassedBack(kErrors[i], ASYNC);
12144 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2412145 }
12146}
12147
[email protected]bd0b6772011-01-11 19:59:3012148// Ensure that a client certificate is removed from the SSL client auth
12149// cache when:
12150// 1) No proxy is involved.
12151// 2) TLS False Start is disabled.
12152// 3) The initial TLS handshake requests a client certificate.
12153// 4) The client supplies an invalid/unacceptable certificate.
[email protected]23e482282013-06-14 16:08:0212154TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2312155 ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912156 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712157 request_info.url = GURL("https://www.example.com/");
12158 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912159 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712160
[email protected]bd0b6772011-01-11 19:59:3012161 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112162 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012163
12164 // [ssl_]data1 contains the data for the first SSL handshake. When a
12165 // CertificateRequest is received for the first time, the handshake will
12166 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2912167 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012168 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712169 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912170 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712171 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012172
12173 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
12174 // False Start is not being used, the result of the SSL handshake will be
12175 // returned as part of the SSLClientSocket::Connect() call. This test
12176 // matches the result of a server sending a handshake_failure alert,
12177 // rather than a Finished message, because it requires a client
12178 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2912179 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012180 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712181 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912182 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712183 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012184
12185 // [ssl_]data3 contains the data for the third SSL handshake. When a
12186 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212187 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
12188 // connection was attempted with TLSv1.2. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3012189 // of the HttpNetworkTransaction. Because this test failure is due to
12190 // requiring a client certificate, this fallback handshake should also
12191 // fail.
ttuttle859dc7a2015-04-23 19:42:2912192 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012193 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712194 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912195 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712196 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012197
[email protected]80c75f682012-05-26 16:22:1712198 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
12199 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212200 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
12201 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1712202 // of the HttpNetworkTransaction. Because this test failure is due to
12203 // requiring a client certificate, this fallback handshake should also
12204 // fail.
ttuttle859dc7a2015-04-23 19:42:2912205 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1712206 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712207 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912208 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712209 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712210
mmenkee65e7af2015-10-13 17:16:4212211 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612212 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012213 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012214
[email protected]bd0b6772011-01-11 19:59:3012215 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4112216 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912217 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12218 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012219
12220 // Complete the SSL handshake, which should abort due to requiring a
12221 // client certificate.
12222 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912223 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]bd0b6772011-01-11 19:59:3012224
12225 // Indicate that no certificate should be supplied. From the perspective
12226 // of SSLClientCertCache, NULL is just as meaningful as a real
12227 // certificate, so this is the same as supply a
12228 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412229 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912230 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012231
12232 // Ensure the certificate was added to the client auth cache before
12233 // allowing the connection to continue restarting.
12234 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412235 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112236 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412237 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012238 ASSERT_EQ(NULL, client_cert.get());
12239
12240 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712241 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12242 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012243 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912244 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
[email protected]bd0b6772011-01-11 19:59:3012245
12246 // Ensure that the client certificate is removed from the cache on a
12247 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112248 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412249 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012250}
12251
12252// Ensure that a client certificate is removed from the SSL client auth
12253// cache when:
12254// 1) No proxy is involved.
12255// 2) TLS False Start is enabled.
12256// 3) The initial TLS handshake requests a client certificate.
12257// 4) The client supplies an invalid/unacceptable certificate.
[email protected]23e482282013-06-14 16:08:0212258TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2312259 ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912260 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712261 request_info.url = GURL("https://www.example.com/");
12262 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912263 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712264
[email protected]bd0b6772011-01-11 19:59:3012265 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112266 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012267
12268 // When TLS False Start is used, SSLClientSocket::Connect() calls will
12269 // return successfully after reading up to the peer's Certificate message.
12270 // This is to allow the caller to call SSLClientSocket::Write(), which can
12271 // enqueue application data to be sent in the same packet as the
12272 // ChangeCipherSpec and Finished messages.
12273 // The actual handshake will be finished when SSLClientSocket::Read() is
12274 // called, which expects to process the peer's ChangeCipherSpec and
12275 // Finished messages. If there was an error negotiating with the peer,
12276 // such as due to the peer requiring a client certificate when none was
12277 // supplied, the alert sent by the peer won't be processed until Read() is
12278 // called.
12279
12280 // Like the non-False Start case, when a client certificate is requested by
12281 // the peer, the handshake is aborted during the Connect() call.
12282 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2912283 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012284 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712285 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912286 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712287 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012288
12289 // When a client certificate is supplied, Connect() will not be aborted
12290 // when the peer requests the certificate. Instead, the handshake will
12291 // artificially succeed, allowing the caller to write the HTTP request to
12292 // the socket. The handshake messages are not processed until Read() is
12293 // called, which then detects that the handshake was aborted, due to the
12294 // peer sending a handshake_failure because it requires a client
12295 // certificate.
ttuttle859dc7a2015-04-23 19:42:2912296 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012297 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712298 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912299 MockRead data2_reads[] = {
12300 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3012301 };
ttuttle859dc7a2015-04-23 19:42:2912302 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712303 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012304
12305 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1712306 // the data for the SSL handshake once the TLSv1.1 connection falls back to
12307 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912308 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012309 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712310 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912311 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712312 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012313
[email protected]80c75f682012-05-26 16:22:1712314 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
12315 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912316 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1712317 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712318 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912319 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712320 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712321
[email protected]7799de12013-05-30 05:52:5112322 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2912323 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5112324 ssl_data5.cert_request_info = cert_request.get();
12325 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
ttuttle859dc7a2015-04-23 19:42:2912326 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]7799de12013-05-30 05:52:5112327 session_deps_.socket_factory->AddSocketDataProvider(&data5);
12328
mmenkee65e7af2015-10-13 17:16:4212329 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612330 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012331 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012332
[email protected]bd0b6772011-01-11 19:59:3012333 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4112334 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912335 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12336 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012337
12338 // Complete the SSL handshake, which should abort due to requiring a
12339 // client certificate.
12340 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912341 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]bd0b6772011-01-11 19:59:3012342
12343 // Indicate that no certificate should be supplied. From the perspective
12344 // of SSLClientCertCache, NULL is just as meaningful as a real
12345 // certificate, so this is the same as supply a
12346 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412347 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912348 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012349
12350 // Ensure the certificate was added to the client auth cache before
12351 // allowing the connection to continue restarting.
12352 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412353 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112354 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412355 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012356 ASSERT_EQ(NULL, client_cert.get());
12357
[email protected]bd0b6772011-01-11 19:59:3012358 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712359 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12360 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012361 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912362 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
[email protected]bd0b6772011-01-11 19:59:3012363
12364 // Ensure that the client certificate is removed from the cache on a
12365 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112366 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412367 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012368}
12369
[email protected]8c405132011-01-11 22:03:1812370// Ensure that a client certificate is removed from the SSL client auth
12371// cache when:
12372// 1) An HTTPS proxy is involved.
12373// 3) The HTTPS proxy requests a client certificate.
12374// 4) The client supplies an invalid/unacceptable certificate for the
12375// proxy.
12376// The test is repeated twice, first for connecting to an HTTPS endpoint,
12377// then for connecting to an HTTP endpoint.
[email protected]23e482282013-06-14 16:08:0212378TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
rdsmith82957ad2015-09-16 19:42:0312379 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:5112380 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712381 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1812382
12383 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112384 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1812385
12386 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
12387 // [ssl_]data[1-3]. Rather than represending the endpoint
12388 // (www.example.com:443), they represent failures with the HTTPS proxy
12389 // (proxy:70).
ttuttle859dc7a2015-04-23 19:42:2912390 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8c405132011-01-11 22:03:1812391 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712392 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912393 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712394 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1812395
ttuttle859dc7a2015-04-23 19:42:2912396 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812397 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712398 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912399 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712400 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8c405132011-01-11 22:03:1812401
[email protected]80c75f682012-05-26 16:22:1712402 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
12403#if 0
ttuttle859dc7a2015-04-23 19:42:2912404 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812405 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712406 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912407 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712408 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]80c75f682012-05-26 16:22:1712409#endif
[email protected]8c405132011-01-11 22:03:1812410
ttuttle859dc7a2015-04-23 19:42:2912411 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1812412 requests[0].url = GURL("https://www.example.com/");
12413 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912414 requests[0].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812415
12416 requests[1].url = GURL("http://www.example.com/");
12417 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912418 requests[1].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812419
12420 for (size_t i = 0; i < arraysize(requests); ++i) {
[email protected]bb88e1d32013-05-03 23:11:0712421 session_deps_.socket_factory->ResetNextMockIndexes();
mmenkee65e7af2015-10-13 17:16:4212422 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c405132011-01-11 22:03:1812423 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5012424 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c405132011-01-11 22:03:1812425
12426 // Begin the SSL handshake with the proxy.
[email protected]49639fa2011-12-20 23:22:4112427 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912428 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
12429 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]8c405132011-01-11 22:03:1812430
12431 // Complete the SSL handshake, which should abort due to requiring a
12432 // client certificate.
12433 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912434 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]8c405132011-01-11 22:03:1812435
12436 // Indicate that no certificate should be supplied. From the perspective
12437 // of SSLClientCertCache, NULL is just as meaningful as a real
12438 // certificate, so this is the same as supply a
12439 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412440 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912441 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]8c405132011-01-11 22:03:1812442
12443 // Ensure the certificate was added to the client auth cache before
12444 // allowing the connection to continue restarting.
12445 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412446 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112447 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412448 HostPortPair("proxy", 70), &client_cert, &client_private_key));
[email protected]8c405132011-01-11 22:03:1812449 ASSERT_EQ(NULL, client_cert.get());
12450 // Ensure the certificate was NOT cached for the endpoint. This only
12451 // applies to HTTPS requests, but is fine to check for HTTP requests.
[email protected]791879c2013-12-17 07:22:4112452 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412453 HostPortPair("www.example.com", 443), &client_cert,
12454 &client_private_key));
[email protected]8c405132011-01-11 22:03:1812455
12456 // Restart the handshake. This will consume ssl_data2, which fails, and
12457 // then consume ssl_data3, which should also fail. The result code is
12458 // checked against what ssl_data3 should return.
12459 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912460 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]8c405132011-01-11 22:03:1812461
12462 // Now that the new handshake has failed, ensure that the client
12463 // certificate was removed from the client auth cache.
[email protected]791879c2013-12-17 07:22:4112464 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412465 HostPortPair("proxy", 70), &client_cert, &client_private_key));
[email protected]791879c2013-12-17 07:22:4112466 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412467 HostPortPair("www.example.com", 443), &client_cert,
12468 &client_private_key));
[email protected]8c405132011-01-11 22:03:1812469 }
12470}
12471
mmenke5c642132015-06-02 16:05:1312472TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
bnc55ff9da2015-08-19 18:42:3512473 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312474 session_deps_.next_protos = SpdyNextProtos();
[email protected]e3ceb682011-06-28 23:55:4612475
12476 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712477 session_deps_.host_resolver.reset(new MockCachingHostResolver());
mmenkee65e7af2015-10-13 17:16:4212478 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2612479 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12480 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4612481
[email protected]8ddf8322012-02-23 18:08:0612482 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812483 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712484 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4612485
[email protected]cdf8f7e72013-05-23 10:56:4612486 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2312487 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812488 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4612489 scoped_ptr<SpdyFrame> host2_req(
12490 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4612491 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312492 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4612493 };
[email protected]23e482282013-06-14 16:08:0212494 scoped_ptr<SpdyFrame> host1_resp(
12495 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12496 scoped_ptr<SpdyFrame> host1_resp_body(
12497 spdy_util_.ConstructSpdyBodyFrame(1, true));
12498 scoped_ptr<SpdyFrame> host2_resp(
12499 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12500 scoped_ptr<SpdyFrame> host2_resp_body(
12501 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4612502 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312503 CreateMockRead(*host1_resp, 1),
12504 CreateMockRead(*host1_resp_body, 2),
12505 CreateMockRead(*host2_resp, 4),
12506 CreateMockRead(*host2_resp_body, 5),
12507 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4612508 };
12509
[email protected]d2b5f092012-06-08 23:55:0212510 IPAddressNumber ip;
12511 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
12512 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12513 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312514 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12515 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712516 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4612517
[email protected]aa22b242011-11-16 18:58:2912518 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4612519 HttpRequestInfo request1;
12520 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312521 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4612522 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012523 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612524
[email protected]49639fa2011-12-20 23:22:4112525 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612526 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112527 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612528
12529 const HttpResponseInfo* response = trans1.GetResponseInfo();
12530 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012531 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212532 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612533
12534 std::string response_data;
12535 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12536 EXPECT_EQ("hello!", response_data);
12537
12538 // Preload www.gmail.com into HostCache.
12539 HostPortPair host_port("www.gmail.com", 443);
[email protected]5109c1952013-08-20 18:44:1012540 HostResolver::RequestInfo resolve_info(host_port);
[email protected]e3ceb682011-06-28 23:55:4612541 AddressList ignored;
[email protected]5109c1952013-08-20 18:44:1012542 rv = session_deps_.host_resolver->Resolve(resolve_info,
12543 DEFAULT_PRIORITY,
12544 &ignored,
12545 callback.callback(),
12546 NULL,
12547 BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:4712548 EXPECT_EQ(ERR_IO_PENDING, rv);
12549 rv = callback.WaitForResult();
12550 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:4612551
12552 HttpRequestInfo request2;
12553 request2.method = "GET";
12554 request2.url = GURL("https://www.gmail.com/");
12555 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012556 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612557
[email protected]49639fa2011-12-20 23:22:4112558 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612559 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112560 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612561
12562 response = trans2.GetResponseInfo();
12563 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012564 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212565 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612566 EXPECT_TRUE(response->was_fetched_via_spdy);
12567 EXPECT_TRUE(response->was_npn_negotiated);
12568 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12569 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4612570}
12571
[email protected]23e482282013-06-14 16:08:0212572TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
bnc55ff9da2015-08-19 18:42:3512573 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312574 session_deps_.next_protos = SpdyNextProtos();
[email protected]d2b5f092012-06-08 23:55:0212575
12576 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712577 session_deps_.host_resolver.reset(new MockCachingHostResolver());
mmenkee65e7af2015-10-13 17:16:4212578 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0212579 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12580 pool_peer.DisableDomainAuthenticationVerification();
12581
12582 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812583 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712584 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]d2b5f092012-06-08 23:55:0212585
[email protected]cdf8f7e72013-05-23 10:56:4612586 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2312587 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812588 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4612589 scoped_ptr<SpdyFrame> host2_req(
12590 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0212591 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312592 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0212593 };
[email protected]23e482282013-06-14 16:08:0212594 scoped_ptr<SpdyFrame> host1_resp(
12595 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12596 scoped_ptr<SpdyFrame> host1_resp_body(
12597 spdy_util_.ConstructSpdyBodyFrame(1, true));
12598 scoped_ptr<SpdyFrame> host2_resp(
12599 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12600 scoped_ptr<SpdyFrame> host2_resp_body(
12601 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0212602 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312603 CreateMockRead(*host1_resp, 1),
12604 CreateMockRead(*host1_resp_body, 2),
12605 CreateMockRead(*host2_resp, 4),
12606 CreateMockRead(*host2_resp_body, 5),
12607 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0212608 };
12609
12610 IPAddressNumber ip;
12611 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
12612 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12613 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312614 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12615 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712616 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0212617
12618 TestCompletionCallback callback;
12619 HttpRequestInfo request1;
12620 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312621 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0212622 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012623 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0212624
12625 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
12626 EXPECT_EQ(ERR_IO_PENDING, rv);
12627 EXPECT_EQ(OK, callback.WaitForResult());
12628
12629 const HttpResponseInfo* response = trans1.GetResponseInfo();
12630 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012631 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212632 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0212633
12634 std::string response_data;
12635 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12636 EXPECT_EQ("hello!", response_data);
12637
12638 HttpRequestInfo request2;
12639 request2.method = "GET";
12640 request2.url = GURL("https://www.gmail.com/");
12641 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012642 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0212643
12644 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
12645 EXPECT_EQ(ERR_IO_PENDING, rv);
12646 EXPECT_EQ(OK, callback.WaitForResult());
12647
12648 response = trans2.GetResponseInfo();
12649 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012650 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212651 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0212652 EXPECT_TRUE(response->was_fetched_via_spdy);
12653 EXPECT_TRUE(response->was_npn_negotiated);
12654 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12655 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0212656}
12657
ttuttle859dc7a2015-04-23 19:42:2912658class OneTimeCachingHostResolver : public HostResolver {
[email protected]e3ceb682011-06-28 23:55:4612659 public:
12660 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
12661 : host_port_(host_port) {}
dchengb03027d2014-10-21 12:00:2012662 ~OneTimeCachingHostResolver() override {}
[email protected]e3ceb682011-06-28 23:55:4612663
12664 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
12665
12666 // HostResolver methods:
dchengb03027d2014-10-21 12:00:2012667 int Resolve(const RequestInfo& info,
12668 RequestPriority priority,
12669 AddressList* addresses,
12670 const CompletionCallback& callback,
12671 RequestHandle* out_req,
12672 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4012673 return host_resolver_.Resolve(
[email protected]5109c1952013-08-20 18:44:1012674 info, priority, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:4012675 }
12676
dchengb03027d2014-10-21 12:00:2012677 int ResolveFromCache(const RequestInfo& info,
12678 AddressList* addresses,
12679 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4012680 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
12681 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]98e1cd012011-11-08 15:33:0912682 host_resolver_.GetHostCache()->clear();
[email protected]e3ceb682011-06-28 23:55:4612683 return rv;
12684 }
12685
dchengb03027d2014-10-21 12:00:2012686 void CancelRequest(RequestHandle req) override {
[email protected]e3ceb682011-06-28 23:55:4612687 host_resolver_.CancelRequest(req);
12688 }
12689
[email protected]46da33be2011-07-19 21:58:0412690 MockCachingHostResolver* GetMockHostResolver() {
12691 return &host_resolver_;
12692 }
12693
[email protected]e3ceb682011-06-28 23:55:4612694 private:
12695 MockCachingHostResolver host_resolver_;
12696 const HostPortPair host_port_;
12697};
12698
mmenke5c642132015-06-02 16:05:1312699TEST_P(HttpNetworkTransactionTest,
12700 UseIPConnectionPoolingWithHostCacheExpiration) {
bnc55ff9da2015-08-19 18:42:3512701 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312702 session_deps_.next_protos = SpdyNextProtos();
[email protected]e3ceb682011-06-28 23:55:4612703
12704 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
[email protected]e3ceb682011-06-28 23:55:4612705 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
[email protected]c6bf8152012-12-02 07:43:3412706 HttpNetworkSession::Params params =
[email protected]bb88e1d32013-05-03 23:11:0712707 SpdySessionDependencies::CreateSessionParams(&session_deps_);
[email protected]e3ceb682011-06-28 23:55:4612708 params.host_resolver = &host_resolver;
mmenkee65e7af2015-10-13 17:16:4212709 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2612710 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12711 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4612712
[email protected]8ddf8322012-02-23 18:08:0612713 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812714 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712715 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4612716
[email protected]cdf8f7e72013-05-23 10:56:4612717 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2312718 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812719 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4612720 scoped_ptr<SpdyFrame> host2_req(
12721 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4612722 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312723 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4612724 };
[email protected]23e482282013-06-14 16:08:0212725 scoped_ptr<SpdyFrame> host1_resp(
12726 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12727 scoped_ptr<SpdyFrame> host1_resp_body(
12728 spdy_util_.ConstructSpdyBodyFrame(1, true));
12729 scoped_ptr<SpdyFrame> host2_resp(
12730 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12731 scoped_ptr<SpdyFrame> host2_resp_body(
12732 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4612733 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312734 CreateMockRead(*host1_resp, 1),
12735 CreateMockRead(*host1_resp_body, 2),
12736 CreateMockRead(*host2_resp, 4),
12737 CreateMockRead(*host2_resp_body, 5),
12738 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4612739 };
12740
[email protected]d2b5f092012-06-08 23:55:0212741 IPAddressNumber ip;
12742 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
12743 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12744 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312745 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12746 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712747 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4612748
[email protected]aa22b242011-11-16 18:58:2912749 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4612750 HttpRequestInfo request1;
12751 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312752 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4612753 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012754 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612755
[email protected]49639fa2011-12-20 23:22:4112756 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612757 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112758 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612759
12760 const HttpResponseInfo* response = trans1.GetResponseInfo();
12761 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012762 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212763 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612764
12765 std::string response_data;
12766 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12767 EXPECT_EQ("hello!", response_data);
12768
12769 // Preload cache entries into HostCache.
[email protected]5109c1952013-08-20 18:44:1012770 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
[email protected]e3ceb682011-06-28 23:55:4612771 AddressList ignored;
[email protected]5109c1952013-08-20 18:44:1012772 rv = host_resolver.Resolve(resolve_info,
12773 DEFAULT_PRIORITY,
12774 &ignored,
12775 callback.callback(),
12776 NULL,
12777 BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:4712778 EXPECT_EQ(ERR_IO_PENDING, rv);
12779 rv = callback.WaitForResult();
12780 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:4612781
12782 HttpRequestInfo request2;
12783 request2.method = "GET";
12784 request2.url = GURL("https://www.gmail.com/");
12785 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012786 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612787
[email protected]49639fa2011-12-20 23:22:4112788 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612789 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112790 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612791
12792 response = trans2.GetResponseInfo();
12793 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012794 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212795 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612796 EXPECT_TRUE(response->was_fetched_via_spdy);
12797 EXPECT_TRUE(response->was_npn_negotiated);
12798 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12799 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4612800}
12801
[email protected]23e482282013-06-14 16:08:0212802TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2312803 const std::string https_url = "https://www.example.org:8080/";
12804 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0412805
12806 // SPDY GET for HTTPS URL
[email protected]cdf8f7e72013-05-23 10:56:4612807 scoped_ptr<SpdyFrame> req1(
12808 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0412809
12810 MockWrite writes1[] = {
12811 CreateMockWrite(*req1, 0),
12812 };
12813
[email protected]23e482282013-06-14 16:08:0212814 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12815 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]8450d722012-07-02 19:14:0412816 MockRead reads1[] = {
12817 CreateMockRead(*resp1, 1),
12818 CreateMockRead(*body1, 2),
12819 MockRead(ASYNC, ERR_IO_PENDING, 3)
12820 };
12821
rch8e6c6c42015-05-01 14:05:1312822 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
12823 arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0412824 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5712825 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0412826
12827 // HTTP GET for the HTTP URL
12828 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1312829 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3412830 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2312831 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3412832 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0412833 };
12834
12835 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1312836 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
12837 MockRead(ASYNC, 2, "hello"),
12838 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0412839 };
12840
rch8e6c6c42015-05-01 14:05:1312841 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
12842 arraysize(writes2));
[email protected]8450d722012-07-02 19:14:0412843
[email protected]8450d722012-07-02 19:14:0412844 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812845 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712846 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12847 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12848 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0412849
mmenkee65e7af2015-10-13 17:16:4212850 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0412851
12852 // Start the first transaction to set up the SpdySession
12853 HttpRequestInfo request1;
12854 request1.method = "GET";
12855 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0412856 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012857 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0412858 TestCompletionCallback callback1;
12859 EXPECT_EQ(ERR_IO_PENDING,
12860 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3412861 base::MessageLoop::current()->RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0412862
12863 EXPECT_EQ(OK, callback1.WaitForResult());
12864 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12865
12866 // Now, start the HTTP request
12867 HttpRequestInfo request2;
12868 request2.method = "GET";
12869 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0412870 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012871 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0412872 TestCompletionCallback callback2;
12873 EXPECT_EQ(ERR_IO_PENDING,
12874 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3412875 base::MessageLoop::current()->RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0412876
12877 EXPECT_EQ(OK, callback2.WaitForResult());
12878 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12879}
12880
bnc1b0e36852015-04-28 15:32:5912881class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
12882 public:
12883 void Run(bool pooling, bool valid) {
12884 HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org",
12885 443);
12886 HostPortPair alternative("www.example.org", 443);
12887
12888 base::FilePath certs_dir = GetTestCertsDirectory();
12889 scoped_refptr<X509Certificate> cert(
12890 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
12891 ASSERT_TRUE(cert.get());
12892 bool common_name_fallback_used;
12893 EXPECT_EQ(valid,
12894 cert->VerifyNameMatch(origin.host(), &common_name_fallback_used));
12895 EXPECT_TRUE(
12896 cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used));
12897 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812898 ssl.SetNextProto(GetProtocol());
bnc1b0e36852015-04-28 15:32:5912899 ssl.cert = cert;
12900 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12901
12902 // If pooling, then start a request to alternative first to create a
12903 // SpdySession.
12904 std::string url0 = "https://www.example.org:443";
12905 // Second request to origin, which has an alternative service, and could
12906 // open a connection to the alternative host or pool to the existing one.
12907 std::string url1("https://");
12908 url1.append(origin.host());
12909 url1.append(":443");
12910
12911 scoped_ptr<SpdyFrame> req0;
12912 scoped_ptr<SpdyFrame> req1;
12913 scoped_ptr<SpdyFrame> resp0;
12914 scoped_ptr<SpdyFrame> body0;
12915 scoped_ptr<SpdyFrame> resp1;
12916 scoped_ptr<SpdyFrame> body1;
12917 std::vector<MockWrite> writes;
12918 std::vector<MockRead> reads;
12919
12920 if (pooling) {
12921 req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812922 spdy_util_.UpdateWithStreamDestruction(1);
bnc1b0e36852015-04-28 15:32:5912923 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 3, LOWEST));
12924
12925 writes.push_back(CreateMockWrite(*req0, 0));
12926 writes.push_back(CreateMockWrite(*req1, 3));
12927
12928 resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12929 body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
12930 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12931 body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true));
12932
12933 reads.push_back(CreateMockRead(*resp0, 1));
12934 reads.push_back(CreateMockRead(*body0, 2));
12935 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4));
12936 reads.push_back(CreateMockRead(*resp1, 5));
12937 reads.push_back(CreateMockRead(*body1, 6));
12938 reads.push_back(MockRead(ASYNC, OK, 7));
12939 } else {
12940 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 1, LOWEST));
12941
12942 writes.push_back(CreateMockWrite(*req1, 0));
12943
12944 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12945 body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
12946
12947 reads.push_back(CreateMockRead(*resp1, 1));
12948 reads.push_back(CreateMockRead(*body1, 2));
12949 reads.push_back(MockRead(ASYNC, OK, 3));
12950 }
12951
davidben5f8b6bc2015-11-25 03:19:5412952 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
12953 writes.size());
bnc1b0e36852015-04-28 15:32:5912954 session_deps_.socket_factory->AddSocketDataProvider(&data);
12955
12956 // Connection to the origin fails.
12957 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12958 StaticSocketDataProvider data_refused;
12959 data_refused.set_connect_data(mock_connect);
12960 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12961
bnc55ff9da2015-08-19 18:42:3512962 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4212963 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc1b0e36852015-04-28 15:32:5912964 base::WeakPtr<HttpServerProperties> http_server_properties =
12965 session->http_server_properties();
12966 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3812967 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1212968 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc1b0e36852015-04-28 15:32:5912969 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1212970 1.0, expiration);
bnc1b0e36852015-04-28 15:32:5912971
12972 // First request to alternative.
12973 if (pooling) {
12974 scoped_ptr<HttpTransaction> trans0(
12975 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12976 HttpRequestInfo request0;
12977 request0.method = "GET";
12978 request0.url = GURL(url0);
12979 request0.load_flags = 0;
12980 TestCompletionCallback callback0;
12981
12982 int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog());
12983 EXPECT_EQ(ERR_IO_PENDING, rv);
12984 rv = callback0.WaitForResult();
12985 EXPECT_EQ(OK, rv);
12986 }
12987
12988 // Second request to origin.
12989 scoped_ptr<HttpTransaction> trans1(
12990 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12991 HttpRequestInfo request1;
12992 request1.method = "GET";
12993 request1.url = GURL(url1);
12994 request1.load_flags = 0;
12995 TestCompletionCallback callback1;
12996
12997 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
12998 EXPECT_EQ(ERR_IO_PENDING, rv);
rch32320842015-05-16 15:57:0912999 base::MessageLoop::current()->RunUntilIdle();
13000 if (data.IsReadPaused()) {
13001 data.CompleteRead();
13002 }
bnc1b0e36852015-04-28 15:32:5913003 rv = callback1.WaitForResult();
13004 if (valid) {
13005 EXPECT_EQ(OK, rv);
13006 } else {
13007 if (pooling) {
13008 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
13009 } else {
13010 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv);
13011 }
13012 }
13013 }
13014};
13015
rdsmithebb50aa2015-11-12 03:44:3813016INSTANTIATE_TEST_CASE_P(ProtoPlusDepend,
bnc1b0e36852015-04-28 15:32:5913017 AltSvcCertificateVerificationTest,
rdsmithebb50aa2015-11-12 03:44:3813018 testing::Values(kTestCaseSPDY31,
13019 kTestCaseHTTP2NoPriorityDependencies,
13020 kTestCaseHTTP2PriorityDependencies));
bnc1b0e36852015-04-28 15:32:5913021
13022// The alternative service host must exhibit a certificate that is valid for the
13023// origin host. Test that this is enforced when pooling to an existing
13024// connection.
13025TEST_P(AltSvcCertificateVerificationTest, PoolingValid) {
13026 Run(true, true);
13027}
13028
13029TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) {
13030 Run(true, false);
13031}
13032
13033// The alternative service host must exhibit a certificate that is valid for the
13034// origin host. Test that this is enforced when opening a new connection.
13035TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) {
13036 Run(false, true);
13037}
13038
13039TEST_P(AltSvcCertificateVerificationTest, NewConnectionInvalid) {
13040 Run(false, false);
13041}
13042
bnc5452e2a2015-05-08 16:27:4213043// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
13044// with the alternative server. That connection should not be used.
13045TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
13046 HostPortPair origin("origin.example.org", 443);
13047 HostPortPair alternative("alternative.example.org", 443);
13048
13049 // Negotiate HTTP/1.1 with alternative.example.org.
13050 SSLSocketDataProvider ssl(ASYNC, OK);
13051 ssl.SetNextProto(kProtoHTTP11);
13052 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13053
13054 // No data should be read from the alternative, because HTTP/1.1 is
13055 // negotiated.
13056 StaticSocketDataProvider data;
13057 session_deps_.socket_factory->AddSocketDataProvider(&data);
13058
13059 // This test documents that an alternate Job should not be used if HTTP/1.1 is
13060 // negotiated. In order to test this, a failed connection to the origin is
13061 // mocked. This way the request relies on the alternate Job.
13062 StaticSocketDataProvider data_refused;
13063 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13064 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13065
13066 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3513067 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213068 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc5452e2a2015-05-08 16:27:4213069 base::WeakPtr<HttpServerProperties> http_server_properties =
13070 session->http_server_properties();
13071 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813072 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213073 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc5452e2a2015-05-08 16:27:4213074 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213075 1.0, expiration);
bnc5452e2a2015-05-08 16:27:4213076
13077 scoped_ptr<HttpTransaction> trans(
13078 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13079 HttpRequestInfo request;
13080 request.method = "GET";
13081 request.url = GURL("https://origin.example.org:443");
13082 request.load_flags = 0;
13083 TestCompletionCallback callback;
13084
13085 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
13086 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
13087 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13088 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED, callback.GetResult(rv));
13089}
13090
bnc40448a532015-05-11 19:13:1413091// A request to a server with an alternative service fires two Jobs: one to the
13092// origin, and an alternate one to the alternative server. If the former
13093// succeeds, the request should succeed, even if the latter fails because
13094// HTTP/1.1 is negotiated which is insufficient for alternative service.
13095TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
13096 HostPortPair origin("origin.example.org", 443);
13097 HostPortPair alternative("alternative.example.org", 443);
13098
13099 // Negotiate HTTP/1.1 with alternative.
13100 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
13101 alternative_ssl.SetNextProto(kProtoHTTP11);
13102 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
13103
13104 // No data should be read from the alternative, because HTTP/1.1 is
13105 // negotiated.
13106 StaticSocketDataProvider data;
13107 session_deps_.socket_factory->AddSocketDataProvider(&data);
13108
13109 // Negotiate HTTP/1.1 with origin.
13110 SSLSocketDataProvider origin_ssl(ASYNC, OK);
13111 origin_ssl.SetNextProto(kProtoHTTP11);
13112 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
13113
13114 MockWrite http_writes[] = {
13115 MockWrite(
13116 "GET / HTTP/1.1\r\n"
13117 "Host: origin.example.org\r\n"
13118 "Connection: keep-alive\r\n\r\n"),
13119 MockWrite(
13120 "GET /second HTTP/1.1\r\n"
13121 "Host: origin.example.org\r\n"
13122 "Connection: keep-alive\r\n\r\n"),
13123 };
13124
13125 MockRead http_reads[] = {
13126 MockRead("HTTP/1.1 200 OK\r\n"),
13127 MockRead("Content-Type: text/html\r\n"),
13128 MockRead("Content-Length: 6\r\n\r\n"),
13129 MockRead("foobar"),
13130 MockRead("HTTP/1.1 200 OK\r\n"),
13131 MockRead("Content-Type: text/html\r\n"),
13132 MockRead("Content-Length: 7\r\n\r\n"),
13133 MockRead("another"),
13134 };
13135 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13136 http_writes, arraysize(http_writes));
13137 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13138
13139 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3513140 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213141 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc40448a532015-05-11 19:13:1413142 base::WeakPtr<HttpServerProperties> http_server_properties =
13143 session->http_server_properties();
13144 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813145 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213146 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc40448a532015-05-11 19:13:1413147 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213148 1.0, expiration);
bnc40448a532015-05-11 19:13:1413149
13150 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
13151 HttpRequestInfo request1;
13152 request1.method = "GET";
13153 request1.url = GURL("https://origin.example.org:443");
13154 request1.load_flags = 0;
13155 TestCompletionCallback callback1;
13156
13157 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
13158 rv = callback1.GetResult(rv);
13159 EXPECT_EQ(OK, rv);
13160
13161 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
13162 ASSERT_TRUE(response1 != nullptr);
13163 ASSERT_TRUE(response1->headers.get() != nullptr);
13164 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13165
13166 std::string response_data1;
13167 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data1));
13168 EXPECT_EQ("foobar", response_data1);
13169
13170 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
13171 // for alternative service.
13172 EXPECT_TRUE(
13173 http_server_properties->IsAlternativeServiceBroken(alternative_service));
13174
13175 // Since |alternative_service| is broken, a second transaction to origin
13176 // should not start an alternate Job. It should pool to existing connection
13177 // to origin.
13178 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
13179 HttpRequestInfo request2;
13180 request2.method = "GET";
13181 request2.url = GURL("https://origin.example.org:443/second");
13182 request2.load_flags = 0;
13183 TestCompletionCallback callback2;
13184
13185 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
13186 rv = callback2.GetResult(rv);
13187 EXPECT_EQ(OK, rv);
13188
13189 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
13190 ASSERT_TRUE(response2 != nullptr);
13191 ASSERT_TRUE(response2->headers.get() != nullptr);
13192 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
13193
13194 std::string response_data2;
13195 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data2));
13196 EXPECT_EQ("another", response_data2);
13197}
13198
bnc5452e2a2015-05-08 16:27:4213199// Alternative service requires HTTP/2 (or SPDY), but there is already a
13200// HTTP/1.1 socket open to the alternative server. That socket should not be
13201// used.
13202TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
13203 HostPortPair origin("origin.example.org", 443);
13204 HostPortPair alternative("alternative.example.org", 443);
13205 std::string origin_url = "https://origin.example.org:443";
13206 std::string alternative_url = "https://alternative.example.org:443";
13207
13208 // Negotiate HTTP/1.1 with alternative.example.org.
13209 SSLSocketDataProvider ssl(ASYNC, OK);
13210 ssl.SetNextProto(kProtoHTTP11);
13211 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13212
13213 // HTTP/1.1 data for |request1| and |request2|.
13214 MockWrite http_writes[] = {
13215 MockWrite(
13216 "GET / HTTP/1.1\r\n"
13217 "Host: alternative.example.org\r\n"
13218 "Connection: keep-alive\r\n\r\n"),
13219 MockWrite(
13220 "GET / HTTP/1.1\r\n"
13221 "Host: alternative.example.org\r\n"
13222 "Connection: keep-alive\r\n\r\n"),
13223 };
13224
13225 MockRead http_reads[] = {
13226 MockRead(
13227 "HTTP/1.1 200 OK\r\n"
13228 "Content-Type: text/html; charset=iso-8859-1\r\n"
13229 "Content-Length: 40\r\n\r\n"
13230 "first HTTP/1.1 response from alternative"),
13231 MockRead(
13232 "HTTP/1.1 200 OK\r\n"
13233 "Content-Type: text/html; charset=iso-8859-1\r\n"
13234 "Content-Length: 41\r\n\r\n"
13235 "second HTTP/1.1 response from alternative"),
13236 };
13237 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13238 http_writes, arraysize(http_writes));
13239 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13240
13241 // This test documents that an alternate Job should not pool to an already
13242 // existing HTTP/1.1 connection. In order to test this, a failed connection
13243 // to the origin is mocked. This way |request2| relies on the alternate Job.
13244 StaticSocketDataProvider data_refused;
13245 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13246 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13247
13248 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3513249 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213250 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc5452e2a2015-05-08 16:27:4213251 base::WeakPtr<HttpServerProperties> http_server_properties =
13252 session->http_server_properties();
13253 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813254 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213255 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc5452e2a2015-05-08 16:27:4213256 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213257 1.0, expiration);
bnc5452e2a2015-05-08 16:27:4213258
13259 // First transaction to alternative to open an HTTP/1.1 socket.
13260 scoped_ptr<HttpTransaction> trans1(
13261 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13262 HttpRequestInfo request1;
13263 request1.method = "GET";
13264 request1.url = GURL(alternative_url);
13265 request1.load_flags = 0;
13266 TestCompletionCallback callback1;
13267
13268 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
13269 EXPECT_EQ(OK, callback1.GetResult(rv));
13270 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
13271 ASSERT_TRUE(response1);
13272 ASSERT_TRUE(response1->headers.get());
13273 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13274 EXPECT_TRUE(response1->was_npn_negotiated);
13275 EXPECT_FALSE(response1->was_fetched_via_spdy);
13276 std::string response_data1;
13277 ASSERT_EQ(OK, ReadTransaction(trans1.get(), &response_data1));
13278 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
13279
13280 // Request for origin.example.org, which has an alternative service. This
13281 // will start two Jobs: the alternative looks for connections to pool to,
13282 // finds one which is HTTP/1.1, and should ignore it, and should not try to
13283 // open other connections to alternative server. The Job to origin fails, so
13284 // this request fails.
13285 scoped_ptr<HttpTransaction> trans2(
13286 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13287 HttpRequestInfo request2;
13288 request2.method = "GET";
13289 request2.url = GURL(origin_url);
13290 request2.load_flags = 0;
13291 TestCompletionCallback callback2;
13292
13293 rv = trans2->Start(&request2, callback2.callback(), BoundNetLog());
13294 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback2.GetResult(rv));
13295
13296 // Another transaction to alternative. This is to test that the HTTP/1.1
13297 // socket is still open and in the pool.
13298 scoped_ptr<HttpTransaction> trans3(
13299 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13300 HttpRequestInfo request3;
13301 request3.method = "GET";
13302 request3.url = GURL(alternative_url);
13303 request3.load_flags = 0;
13304 TestCompletionCallback callback3;
13305
13306 rv = trans3->Start(&request3, callback3.callback(), BoundNetLog());
13307 EXPECT_EQ(OK, callback3.GetResult(rv));
13308 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
13309 ASSERT_TRUE(response3);
13310 ASSERT_TRUE(response3->headers.get());
13311 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
13312 EXPECT_TRUE(response3->was_npn_negotiated);
13313 EXPECT_FALSE(response3->was_fetched_via_spdy);
13314 std::string response_data3;
13315 ASSERT_EQ(OK, ReadTransaction(trans3.get(), &response_data3));
13316 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
13317}
13318
[email protected]23e482282013-06-14 16:08:0213319TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2313320 const std::string https_url = "https://www.example.org:8080/";
13321 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0413322
rdsmithebb50aa2015-11-12 03:44:3813323 // Separate SPDY util instance for naked and wrapped requests.
13324 SpdyTestUtil spdy_util_wrapped(GetProtocol(), GetDependenciesFromPriority());
13325
[email protected]8450d722012-07-02 19:14:0413326 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2313327 const HostPortPair host_port_pair("www.example.org", 8080);
lgarrona91df87f2014-12-05 00:51:3413328 scoped_ptr<SpdyFrame> connect(
13329 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
[email protected]cdf8f7e72013-05-23 10:56:4613330 scoped_ptr<SpdyFrame> req1(
rdsmithebb50aa2015-11-12 03:44:3813331 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
[email protected]23e482282013-06-14 16:08:0213332 scoped_ptr<SpdyFrame> wrapped_req1(
13333 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3913334
13335 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
[email protected]745aa9c2014-06-27 02:21:2913336 SpdyHeaderBlock req2_block;
bnc7ecc1122015-09-28 13:22:4913337 spdy_util_.MaybeAddVersionHeader(&req2_block);
[email protected]745aa9c2014-06-27 02:21:2913338 req2_block[spdy_util_.GetMethodKey()] = "GET";
bncce36dca22015-04-21 22:11:2313339 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
[email protected]745aa9c2014-06-27 02:21:2913340 req2_block[spdy_util_.GetSchemeKey()] = "http";
bnc7ecc1122015-09-28 13:22:4913341 req2_block[spdy_util_.GetPathKey()] = "/";
[email protected]601e03f12014-04-06 16:26:3913342 scoped_ptr<SpdyFrame> req2(
[email protected]745aa9c2014-06-27 02:21:2913343 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
[email protected]8450d722012-07-02 19:14:0413344
13345 MockWrite writes1[] = {
13346 CreateMockWrite(*connect, 0),
13347 CreateMockWrite(*wrapped_req1, 2),
13348 CreateMockWrite(*req2, 5),
13349 };
13350
[email protected]23e482282013-06-14 16:08:0213351 scoped_ptr<SpdyFrame> conn_resp(
13352 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13353 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13354 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
13355 scoped_ptr<SpdyFrame> wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3813356 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
[email protected]23e482282013-06-14 16:08:0213357 scoped_ptr<SpdyFrame> wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3813358 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
[email protected]23e482282013-06-14 16:08:0213359 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13360 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]8450d722012-07-02 19:14:0413361 MockRead reads1[] = {
13362 CreateMockRead(*conn_resp, 1),
13363 CreateMockRead(*wrapped_resp1, 3),
13364 CreateMockRead(*wrapped_body1, 4),
13365 CreateMockRead(*resp2, 6),
13366 CreateMockRead(*body2, 7),
13367 MockRead(ASYNC, ERR_IO_PENDING, 8)
13368 };
13369
[email protected]dd54bd82012-07-19 23:44:5713370 DeterministicSocketData data1(reads1, arraysize(reads1),
13371 writes1, arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0413372 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5713373 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0413374
rdsmith82957ad2015-09-16 19:42:0313375 session_deps_.proxy_service =
13376 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:5113377 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0713378 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0413379 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
rdsmithebb50aa2015-11-12 03:44:3813380 ssl1.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713381 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0413382 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
rdsmithebb50aa2015-11-12 03:44:3813383 ssl2.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713384 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
13385 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0413386
mmenkee65e7af2015-10-13 17:16:4213387 scoped_ptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:0713388 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
[email protected]8450d722012-07-02 19:14:0413389
13390 // Start the first transaction to set up the SpdySession
13391 HttpRequestInfo request1;
13392 request1.method = "GET";
13393 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0413394 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013395 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0413396 TestCompletionCallback callback1;
13397 EXPECT_EQ(ERR_IO_PENDING,
13398 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413399 base::MessageLoop::current()->RunUntilIdle();
[email protected]dd54bd82012-07-19 23:44:5713400 data1.RunFor(4);
[email protected]8450d722012-07-02 19:14:0413401
13402 EXPECT_EQ(OK, callback1.WaitForResult());
13403 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13404
[email protected]f6c63db52013-02-02 00:35:2213405 LoadTimingInfo load_timing_info1;
13406 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
13407 TestLoadTimingNotReusedWithPac(load_timing_info1,
13408 CONNECT_TIMING_HAS_SSL_TIMES);
13409
[email protected]8450d722012-07-02 19:14:0413410 // Now, start the HTTP request
13411 HttpRequestInfo request2;
13412 request2.method = "GET";
13413 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0413414 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013415 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0413416 TestCompletionCallback callback2;
13417 EXPECT_EQ(ERR_IO_PENDING,
13418 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413419 base::MessageLoop::current()->RunUntilIdle();
[email protected]dd54bd82012-07-19 23:44:5713420 data1.RunFor(3);
[email protected]8450d722012-07-02 19:14:0413421
13422 EXPECT_EQ(OK, callback2.WaitForResult());
13423 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2213424
13425 LoadTimingInfo load_timing_info2;
13426 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
13427 // The established SPDY sessions is considered reused by the HTTP request.
13428 TestLoadTimingReusedWithPac(load_timing_info2);
13429 // HTTP requests over a SPDY session should have a different connection
13430 // socket_log_id than requests over a tunnel.
13431 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0413432}
13433
[email protected]2d88e7d2012-07-19 17:55:1713434// Test that in the case where we have a SPDY session to a SPDY proxy
13435// that we do not pool other origins that resolve to the same IP when
13436// the certificate does not match the new origin.
13437// http://crbug.com/134690
[email protected]23e482282013-06-14 16:08:0213438TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2313439 const std::string url1 = "http://www.example.org/";
13440 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1713441 const std::string ip_addr = "1.2.3.4";
13442
rdsmithebb50aa2015-11-12 03:44:3813443 // Second SpdyTestUtil instance for the second socket.
13444 SpdyTestUtil spdy_util_secure(GetProtocol(), GetDependenciesFromPriority());
13445
[email protected]2d88e7d2012-07-19 17:55:1713446 // SPDY GET for HTTP URL (through SPDY proxy)
[email protected]23e482282013-06-14 16:08:0213447 scoped_ptr<SpdyHeaderBlock> headers(
bncce36dca22015-04-21 22:11:2313448 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
[email protected]745aa9c2014-06-27 02:21:2913449 scoped_ptr<SpdyFrame> req1(
13450 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]2d88e7d2012-07-19 17:55:1713451
13452 MockWrite writes1[] = {
13453 CreateMockWrite(*req1, 0),
13454 };
13455
[email protected]23e482282013-06-14 16:08:0213456 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13457 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1713458 MockRead reads1[] = {
bncb9e20fc62015-08-17 17:19:3713459 CreateMockRead(*resp1, 1),
13460 CreateMockRead(*body1, 2),
13461 MockRead(ASYNC, OK, 3) // EOF
[email protected]2d88e7d2012-07-19 17:55:1713462 };
13463
13464 scoped_ptr<DeterministicSocketData> data1(
13465 new DeterministicSocketData(reads1, arraysize(reads1),
13466 writes1, arraysize(writes1)));
13467 IPAddressNumber ip;
13468 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
13469 IPEndPoint peer_addr = IPEndPoint(ip, 443);
13470 MockConnect connect_data1(ASYNC, OK, peer_addr);
13471 data1->set_connect_data(connect_data1);
13472
13473 // SPDY GET for HTTPS URL (direct)
[email protected]cdf8f7e72013-05-23 10:56:4613474 scoped_ptr<SpdyFrame> req2(
rdsmithebb50aa2015-11-12 03:44:3813475 spdy_util_secure.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1713476
13477 MockWrite writes2[] = {
13478 CreateMockWrite(*req2, 0),
13479 };
13480
rdsmithebb50aa2015-11-12 03:44:3813481 scoped_ptr<SpdyFrame> resp2(
13482 spdy_util_secure.ConstructSpdyGetSynReply(NULL, 0, 1));
13483 scoped_ptr<SpdyFrame> body2(spdy_util_secure.ConstructSpdyBodyFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1713484 MockRead reads2[] = {
bncb9e20fc62015-08-17 17:19:3713485 CreateMockRead(*resp2, 1),
13486 CreateMockRead(*body2, 2),
13487 MockRead(ASYNC, OK, 3) // EOF
[email protected]2d88e7d2012-07-19 17:55:1713488 };
13489
13490 scoped_ptr<DeterministicSocketData> data2(
13491 new DeterministicSocketData(reads2, arraysize(reads2),
13492 writes2, arraysize(writes2)));
13493 MockConnect connect_data2(ASYNC, OK);
13494 data2->set_connect_data(connect_data2);
13495
13496 // Set up a proxy config that sends HTTP requests to a proxy, and
13497 // all others direct.
13498 ProxyConfig proxy_config;
13499 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
[email protected]bb88e1d32013-05-03 23:11:0713500 session_deps_.proxy_service.reset(new ProxyService(
csharrisonb7e3a082015-09-22 19:13:0413501 make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)), nullptr,
13502 NULL));
[email protected]2d88e7d2012-07-19 17:55:1713503
bncce36dca22015-04-21 22:11:2313504 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
rdsmithebb50aa2015-11-12 03:44:3813505 ssl1.SetNextProto(GetProtocol());
[email protected]2d88e7d2012-07-19 17:55:1713506 // Load a valid cert. Note, that this does not need to
13507 // be valid for proxy because the MockSSLClientSocket does
13508 // not actually verify it. But SpdySession will use this
13509 // to see if it is valid for the new origin
bncce36dca22015-04-21 22:11:2313510 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
13511 ASSERT_TRUE(ssl1.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0713512 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
13513 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
13514 data1.get());
[email protected]2d88e7d2012-07-19 17:55:1713515
13516 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
rdsmithebb50aa2015-11-12 03:44:3813517 ssl2.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713518 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
13519 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
13520 data2.get());
[email protected]2d88e7d2012-07-19 17:55:1713521
[email protected]bb88e1d32013-05-03 23:11:0713522 session_deps_.host_resolver.reset(new MockCachingHostResolver());
bncce36dca22015-04-21 22:11:2313523 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0713524 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1713525
mmenkee65e7af2015-10-13 17:16:4213526 scoped_ptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:0713527 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
[email protected]2d88e7d2012-07-19 17:55:1713528
13529 // Start the first transaction to set up the SpdySession
13530 HttpRequestInfo request1;
13531 request1.method = "GET";
13532 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1713533 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013534 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713535 TestCompletionCallback callback1;
13536 ASSERT_EQ(ERR_IO_PENDING,
13537 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
13538 data1->RunFor(3);
13539
13540 ASSERT_TRUE(callback1.have_result());
13541 EXPECT_EQ(OK, callback1.WaitForResult());
13542 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13543
13544 // Now, start the HTTP request
13545 HttpRequestInfo request2;
13546 request2.method = "GET";
13547 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1713548 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013549 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713550 TestCompletionCallback callback2;
13551 EXPECT_EQ(ERR_IO_PENDING,
13552 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413553 base::MessageLoop::current()->RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1713554 data2->RunFor(3);
13555
13556 ASSERT_TRUE(callback2.have_result());
13557 EXPECT_EQ(OK, callback2.WaitForResult());
13558 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13559}
13560
[email protected]85f97342013-04-17 06:12:2413561// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
13562// error) in SPDY session, removes the socket from pool and closes the SPDY
13563// session. Verify that new url's from the same HttpNetworkSession (and a new
13564// SpdySession) do work. http://crbug.com/224701
[email protected]23e482282013-06-14 16:08:0213565TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2313566 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2413567
13568 MockRead reads1[] = {
13569 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
13570 };
13571
mmenke11eb5152015-06-09 14:50:5013572 SequencedSocketData data1(reads1, arraysize(reads1), NULL, 0);
[email protected]85f97342013-04-17 06:12:2413573
[email protected]cdf8f7e72013-05-23 10:56:4613574 scoped_ptr<SpdyFrame> req2(
13575 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2413576 MockWrite writes2[] = {
13577 CreateMockWrite(*req2, 0),
13578 };
13579
[email protected]23e482282013-06-14 16:08:0213580 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13581 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]85f97342013-04-17 06:12:2413582 MockRead reads2[] = {
13583 CreateMockRead(*resp2, 1),
13584 CreateMockRead(*body2, 2),
13585 MockRead(ASYNC, OK, 3) // EOF
13586 };
13587
mmenke11eb5152015-06-09 14:50:5013588 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13589 arraysize(writes2));
[email protected]85f97342013-04-17 06:12:2413590
[email protected]85f97342013-04-17 06:12:2413591 SSLSocketDataProvider ssl1(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813592 ssl1.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:5013593 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13594 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2413595
13596 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813597 ssl2.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:5013598 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13599 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2413600
mmenkee65e7af2015-10-13 17:16:4213601 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5013602 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2413603
13604 // Start the first transaction to set up the SpdySession and verify that
13605 // connection was closed.
13606 HttpRequestInfo request1;
13607 request1.method = "GET";
13608 request1.url = GURL(https_url);
13609 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013610 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2413611 TestCompletionCallback callback1;
13612 EXPECT_EQ(ERR_IO_PENDING,
13613 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]85f97342013-04-17 06:12:2413614 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
13615
13616 // Now, start the second request and make sure it succeeds.
13617 HttpRequestInfo request2;
13618 request2.method = "GET";
13619 request2.url = GURL(https_url);
13620 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013621 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2413622 TestCompletionCallback callback2;
13623 EXPECT_EQ(ERR_IO_PENDING,
13624 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]85f97342013-04-17 06:12:2413625
mmenke11eb5152015-06-09 14:50:5013626 ASSERT_EQ(OK, callback2.WaitForResult());
[email protected]85f97342013-04-17 06:12:2413627 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13628}
13629
[email protected]23e482282013-06-14 16:08:0213630TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]d7599122014-05-24 03:37:2313631 session_deps_.next_protos = SpdyNextProtos();
[email protected]483fa202013-05-14 01:07:0313632 ClientSocketPoolManager::set_max_sockets_per_group(
13633 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13634 ClientSocketPoolManager::set_max_sockets_per_pool(
13635 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13636
13637 // Use two different hosts with different IPs so they don't get pooled.
13638 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
13639 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
mmenkee65e7af2015-10-13 17:16:4213640 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0313641
13642 SSLSocketDataProvider ssl1(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813643 ssl1.SetNextProto(GetProtocol());
[email protected]483fa202013-05-14 01:07:0313644 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813645 ssl2.SetNextProto(GetProtocol());
[email protected]483fa202013-05-14 01:07:0313646 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13647 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13648
[email protected]cdf8f7e72013-05-23 10:56:4613649 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
[email protected]483fa202013-05-14 01:07:0313650 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
13651 MockWrite spdy1_writes[] = {
rch8e6c6c42015-05-01 14:05:1313652 CreateMockWrite(*host1_req, 0),
[email protected]483fa202013-05-14 01:07:0313653 };
[email protected]23e482282013-06-14 16:08:0213654 scoped_ptr<SpdyFrame> host1_resp(
13655 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13656 scoped_ptr<SpdyFrame> host1_resp_body(
13657 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]483fa202013-05-14 01:07:0313658 MockRead spdy1_reads[] = {
rch8e6c6c42015-05-01 14:05:1313659 CreateMockRead(*host1_resp, 1),
13660 CreateMockRead(*host1_resp_body, 2),
13661 MockRead(ASYNC, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0313662 };
13663
rdsmithebb50aa2015-11-12 03:44:3813664 // Use a separate test instance for the separate SpdySession that will be
13665 // created.
13666 SpdyTestUtil spdy_util_2(GetProtocol(), GetDependenciesFromPriority());
rch8e6c6c42015-05-01 14:05:1313667 scoped_ptr<SequencedSocketData> spdy1_data(
13668 new SequencedSocketData(spdy1_reads, arraysize(spdy1_reads), spdy1_writes,
13669 arraysize(spdy1_writes)));
[email protected]483fa202013-05-14 01:07:0313670 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
13671
rdsmithebb50aa2015-11-12 03:44:3813672 scoped_ptr<SpdyFrame> host2_req(spdy_util_2.ConstructSpdyGet(
[email protected]483fa202013-05-14 01:07:0313673 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
13674 MockWrite spdy2_writes[] = {
rch8e6c6c42015-05-01 14:05:1313675 CreateMockWrite(*host2_req, 0),
[email protected]483fa202013-05-14 01:07:0313676 };
[email protected]23e482282013-06-14 16:08:0213677 scoped_ptr<SpdyFrame> host2_resp(
rdsmithebb50aa2015-11-12 03:44:3813678 spdy_util_2.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]23e482282013-06-14 16:08:0213679 scoped_ptr<SpdyFrame> host2_resp_body(
rdsmithebb50aa2015-11-12 03:44:3813680 spdy_util_2.ConstructSpdyBodyFrame(1, true));
[email protected]483fa202013-05-14 01:07:0313681 MockRead spdy2_reads[] = {
rch8e6c6c42015-05-01 14:05:1313682 CreateMockRead(*host2_resp, 1),
13683 CreateMockRead(*host2_resp_body, 2),
13684 MockRead(ASYNC, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0313685 };
13686
rch8e6c6c42015-05-01 14:05:1313687 scoped_ptr<SequencedSocketData> spdy2_data(
13688 new SequencedSocketData(spdy2_reads, arraysize(spdy2_reads), spdy2_writes,
13689 arraysize(spdy2_writes)));
[email protected]483fa202013-05-14 01:07:0313690 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
13691
13692 MockWrite http_write[] = {
13693 MockWrite("GET / HTTP/1.1\r\n"
13694 "Host: www.a.com\r\n"
13695 "Connection: keep-alive\r\n\r\n"),
13696 };
13697
13698 MockRead http_read[] = {
13699 MockRead("HTTP/1.1 200 OK\r\n"),
13700 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
13701 MockRead("Content-Length: 6\r\n\r\n"),
13702 MockRead("hello!"),
13703 };
13704 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
13705 http_write, arraysize(http_write));
13706 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13707
13708 HostPortPair host_port_pair_a("www.a.com", 443);
[email protected]e6d017652013-05-17 18:01:4013709 SpdySessionKey spdy_session_key_a(
[email protected]314b03992014-04-01 01:28:5313710 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0313711 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613712 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313713
13714 TestCompletionCallback callback;
13715 HttpRequestInfo request1;
13716 request1.method = "GET";
13717 request1.url = GURL("https://www.a.com/");
13718 request1.load_flags = 0;
13719 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5013720 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0313721
13722 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
13723 EXPECT_EQ(ERR_IO_PENDING, rv);
13724 EXPECT_EQ(OK, callback.WaitForResult());
13725
13726 const HttpResponseInfo* response = trans->GetResponseInfo();
13727 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013728 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0213729 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0313730 EXPECT_TRUE(response->was_fetched_via_spdy);
13731 EXPECT_TRUE(response->was_npn_negotiated);
13732
13733 std::string response_data;
13734 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
13735 EXPECT_EQ("hello!", response_data);
13736 trans.reset();
13737 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2613738 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313739
13740 HostPortPair host_port_pair_b("www.b.com", 443);
[email protected]e6d017652013-05-17 18:01:4013741 SpdySessionKey spdy_session_key_b(
[email protected]314b03992014-04-01 01:28:5313742 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0313743 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613744 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0313745 HttpRequestInfo request2;
13746 request2.method = "GET";
13747 request2.url = GURL("https://www.b.com/");
13748 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013749 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0313750
13751 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
13752 EXPECT_EQ(ERR_IO_PENDING, rv);
13753 EXPECT_EQ(OK, callback.WaitForResult());
13754
13755 response = trans->GetResponseInfo();
13756 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013757 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0213758 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0313759 EXPECT_TRUE(response->was_fetched_via_spdy);
13760 EXPECT_TRUE(response->was_npn_negotiated);
13761 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
13762 EXPECT_EQ("hello!", response_data);
13763 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613764 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313765 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2613766 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0313767
13768 HostPortPair host_port_pair_a1("www.a.com", 80);
[email protected]e6d017652013-05-17 18:01:4013769 SpdySessionKey spdy_session_key_a1(
[email protected]314b03992014-04-01 01:28:5313770 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0313771 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613772 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0313773 HttpRequestInfo request3;
13774 request3.method = "GET";
13775 request3.url = GURL("http://www.a.com/");
13776 request3.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013777 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0313778
13779 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
13780 EXPECT_EQ(ERR_IO_PENDING, rv);
13781 EXPECT_EQ(OK, callback.WaitForResult());
13782
13783 response = trans->GetResponseInfo();
13784 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013785 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]483fa202013-05-14 01:07:0313786 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13787 EXPECT_FALSE(response->was_fetched_via_spdy);
13788 EXPECT_FALSE(response->was_npn_negotiated);
13789 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
13790 EXPECT_EQ("hello!", response_data);
13791 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613792 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313793 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613794 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0313795}
13796
[email protected]79e1fd62013-06-20 06:50:0413797TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
13798 HttpRequestInfo request;
13799 request.method = "GET";
bncce36dca22015-04-21 22:11:2313800 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413801 request.load_flags = 0;
13802
mmenkee65e7af2015-10-13 17:16:4213803 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0413804 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113805 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413806
ttuttled9dbc652015-09-29 20:00:5913807 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0413808 StaticSocketDataProvider data;
13809 data.set_connect_data(mock_connect);
13810 session_deps_.socket_factory->AddSocketDataProvider(&data);
13811
13812 TestCompletionCallback callback;
13813
13814 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13815 EXPECT_EQ(ERR_IO_PENDING, rv);
13816
13817 rv = callback.WaitForResult();
ttuttled9dbc652015-09-29 20:00:5913818 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
[email protected]79e1fd62013-06-20 06:50:0413819
[email protected]79e1fd62013-06-20 06:50:0413820 // We don't care whether this succeeds or fails, but it shouldn't crash.
13821 HttpRequestHeaders request_headers;
13822 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4713823
13824 ConnectionAttempts attempts;
13825 trans->GetConnectionAttempts(&attempts);
13826 ASSERT_EQ(1u, attempts.size());
ttuttled9dbc652015-09-29 20:00:5913827 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
13828
13829 IPEndPoint endpoint;
13830 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
13831 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0413832}
13833
13834TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
13835 HttpRequestInfo request;
13836 request.method = "GET";
bncce36dca22015-04-21 22:11:2313837 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413838 request.load_flags = 0;
13839
mmenkee65e7af2015-10-13 17:16:4213840 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0413841 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113842 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413843
ttuttled9dbc652015-09-29 20:00:5913844 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0413845 StaticSocketDataProvider data;
13846 data.set_connect_data(mock_connect);
13847 session_deps_.socket_factory->AddSocketDataProvider(&data);
13848
13849 TestCompletionCallback callback;
13850
13851 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13852 EXPECT_EQ(ERR_IO_PENDING, rv);
13853
13854 rv = callback.WaitForResult();
ttuttled9dbc652015-09-29 20:00:5913855 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
[email protected]79e1fd62013-06-20 06:50:0413856
[email protected]79e1fd62013-06-20 06:50:0413857 // We don't care whether this succeeds or fails, but it shouldn't crash.
13858 HttpRequestHeaders request_headers;
13859 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4713860
13861 ConnectionAttempts attempts;
13862 trans->GetConnectionAttempts(&attempts);
13863 ASSERT_EQ(1u, attempts.size());
ttuttled9dbc652015-09-29 20:00:5913864 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
13865
13866 IPEndPoint endpoint;
13867 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
13868 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0413869}
13870
13871TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
13872 HttpRequestInfo request;
13873 request.method = "GET";
bncce36dca22015-04-21 22:11:2313874 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413875 request.load_flags = 0;
13876
mmenkee65e7af2015-10-13 17:16:4213877 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0413878 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113879 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413880
13881 MockWrite data_writes[] = {
13882 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13883 };
13884 MockRead data_reads[] = {
13885 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
13886 };
13887
13888 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13889 data_writes, arraysize(data_writes));
13890 session_deps_.socket_factory->AddSocketDataProvider(&data);
13891
13892 TestCompletionCallback callback;
13893
13894 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13895 EXPECT_EQ(ERR_IO_PENDING, rv);
13896
13897 rv = callback.WaitForResult();
13898 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13899
[email protected]79e1fd62013-06-20 06:50:0413900 HttpRequestHeaders request_headers;
13901 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13902 EXPECT_TRUE(request_headers.HasHeader("Host"));
13903}
13904
13905TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
13906 HttpRequestInfo request;
13907 request.method = "GET";
bncce36dca22015-04-21 22:11:2313908 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413909 request.load_flags = 0;
13910
mmenkee65e7af2015-10-13 17:16:4213911 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0413912 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113913 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413914
13915 MockWrite data_writes[] = {
13916 MockWrite(ASYNC, ERR_CONNECTION_RESET),
13917 };
13918 MockRead data_reads[] = {
13919 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
13920 };
13921
13922 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13923 data_writes, arraysize(data_writes));
13924 session_deps_.socket_factory->AddSocketDataProvider(&data);
13925
13926 TestCompletionCallback callback;
13927
13928 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13929 EXPECT_EQ(ERR_IO_PENDING, rv);
13930
13931 rv = callback.WaitForResult();
13932 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13933
[email protected]79e1fd62013-06-20 06:50:0413934 HttpRequestHeaders request_headers;
13935 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13936 EXPECT_TRUE(request_headers.HasHeader("Host"));
13937}
13938
13939TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
13940 HttpRequestInfo request;
13941 request.method = "GET";
bncce36dca22015-04-21 22:11:2313942 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413943 request.load_flags = 0;
13944
mmenkee65e7af2015-10-13 17:16:4213945 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0413946 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113947 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413948
13949 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2313950 MockWrite(
13951 "GET / HTTP/1.1\r\n"
13952 "Host: www.example.org\r\n"
13953 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0413954 };
13955 MockRead data_reads[] = {
13956 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
13957 };
13958
13959 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13960 data_writes, arraysize(data_writes));
13961 session_deps_.socket_factory->AddSocketDataProvider(&data);
13962
13963 TestCompletionCallback callback;
13964
13965 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13966 EXPECT_EQ(ERR_IO_PENDING, rv);
13967
13968 rv = callback.WaitForResult();
13969 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13970
[email protected]79e1fd62013-06-20 06:50:0413971 HttpRequestHeaders request_headers;
13972 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13973 EXPECT_TRUE(request_headers.HasHeader("Host"));
13974}
13975
13976TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
13977 HttpRequestInfo request;
13978 request.method = "GET";
bncce36dca22015-04-21 22:11:2313979 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413980 request.load_flags = 0;
13981
mmenkee65e7af2015-10-13 17:16:4213982 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0413983 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113984 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413985
13986 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2313987 MockWrite(
13988 "GET / HTTP/1.1\r\n"
13989 "Host: www.example.org\r\n"
13990 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0413991 };
13992 MockRead data_reads[] = {
13993 MockRead(ASYNC, ERR_CONNECTION_RESET),
13994 };
13995
13996 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13997 data_writes, arraysize(data_writes));
13998 session_deps_.socket_factory->AddSocketDataProvider(&data);
13999
14000 TestCompletionCallback callback;
14001
14002 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14003 EXPECT_EQ(ERR_IO_PENDING, rv);
14004
14005 rv = callback.WaitForResult();
14006 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14007
[email protected]79e1fd62013-06-20 06:50:0414008 HttpRequestHeaders request_headers;
14009 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14010 EXPECT_TRUE(request_headers.HasHeader("Host"));
14011}
14012
14013TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
14014 HttpRequestInfo request;
14015 request.method = "GET";
bncce36dca22015-04-21 22:11:2314016 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414017 request.load_flags = 0;
14018 request.extra_headers.SetHeader("X-Foo", "bar");
14019
mmenkee65e7af2015-10-13 17:16:4214020 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414021 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114022 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414023
14024 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314025 MockWrite(
14026 "GET / HTTP/1.1\r\n"
14027 "Host: www.example.org\r\n"
14028 "Connection: keep-alive\r\n"
14029 "X-Foo: bar\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414030 };
14031 MockRead data_reads[] = {
14032 MockRead("HTTP/1.1 200 OK\r\n"
14033 "Content-Length: 5\r\n\r\n"
14034 "hello"),
14035 MockRead(ASYNC, ERR_UNEXPECTED),
14036 };
14037
14038 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14039 data_writes, arraysize(data_writes));
14040 session_deps_.socket_factory->AddSocketDataProvider(&data);
14041
14042 TestCompletionCallback callback;
14043
14044 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14045 EXPECT_EQ(ERR_IO_PENDING, rv);
14046
14047 rv = callback.WaitForResult();
14048 EXPECT_EQ(OK, rv);
14049
14050 HttpRequestHeaders request_headers;
14051 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14052 std::string foo;
14053 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
14054 EXPECT_EQ("bar", foo);
14055}
14056
[email protected]bf828982013-08-14 18:01:4714057namespace {
14058
yhiranoa7e05bb2014-11-06 05:40:3914059// Fake HttpStream that simply records calls to SetPriority().
14060class FakeStream : public HttpStream,
[email protected]e86839fd2013-08-14 18:29:0314061 public base::SupportsWeakPtr<FakeStream> {
14062 public:
14063 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
dchengb03027d2014-10-21 12:00:2014064 ~FakeStream() override {}
[email protected]e86839fd2013-08-14 18:29:0314065
14066 RequestPriority priority() const { return priority_; }
14067
dchengb03027d2014-10-21 12:00:2014068 int InitializeStream(const HttpRequestInfo* request_info,
14069 RequestPriority priority,
14070 const BoundNetLog& net_log,
14071 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314072 return ERR_IO_PENDING;
14073 }
14074
dchengb03027d2014-10-21 12:00:2014075 int SendRequest(const HttpRequestHeaders& request_headers,
14076 HttpResponseInfo* response,
14077 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314078 ADD_FAILURE();
14079 return ERR_UNEXPECTED;
14080 }
14081
dchengb03027d2014-10-21 12:00:2014082 int ReadResponseHeaders(const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314083 ADD_FAILURE();
14084 return ERR_UNEXPECTED;
14085 }
14086
dchengb03027d2014-10-21 12:00:2014087 int ReadResponseBody(IOBuffer* buf,
14088 int buf_len,
14089 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314090 ADD_FAILURE();
14091 return ERR_UNEXPECTED;
14092 }
14093
dchengb03027d2014-10-21 12:00:2014094 void Close(bool not_reusable) override {}
[email protected]e86839fd2013-08-14 18:29:0314095
dchengb03027d2014-10-21 12:00:2014096 bool IsResponseBodyComplete() const override {
[email protected]e86839fd2013-08-14 18:29:0314097 ADD_FAILURE();
14098 return false;
14099 }
14100
dchengb03027d2014-10-21 12:00:2014101 bool IsConnectionReused() const override {
[email protected]e86839fd2013-08-14 18:29:0314102 ADD_FAILURE();
14103 return false;
14104 }
14105
dchengb03027d2014-10-21 12:00:2014106 void SetConnectionReused() override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0314107
mmenkebd84c392015-09-02 14:12:3414108 bool CanReuseConnection() const override { return false; }
[email protected]e86839fd2013-08-14 18:29:0314109
sclittle4de1bab92015-09-22 21:28:2414110 int64_t GetTotalReceivedBytes() const override {
[email protected]bc92bc972013-12-13 08:32:5914111 ADD_FAILURE();
14112 return 0;
14113 }
14114
sclittlebe1ccf62015-09-02 19:40:3614115 int64_t GetTotalSentBytes() const override {
14116 ADD_FAILURE();
14117 return 0;
14118 }
14119
dchengb03027d2014-10-21 12:00:2014120 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
[email protected]e86839fd2013-08-14 18:29:0314121 ADD_FAILURE();
14122 return false;
14123 }
14124
dchengb03027d2014-10-21 12:00:2014125 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
14126
14127 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
[email protected]e86839fd2013-08-14 18:29:0314128 ADD_FAILURE();
14129 }
14130
ttuttled9dbc652015-09-29 20:00:5914131 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
14132
dchengb03027d2014-10-21 12:00:2014133 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0314134
dchengb03027d2014-10-21 12:00:2014135 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]e86839fd2013-08-14 18:29:0314136
yhiranoa7e05bb2014-11-06 05:40:3914137 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
14138
14139 HttpStream* RenewStreamForAuth() override { return NULL; }
14140
[email protected]e86839fd2013-08-14 18:29:0314141 private:
14142 RequestPriority priority_;
14143
14144 DISALLOW_COPY_AND_ASSIGN(FakeStream);
14145};
14146
14147// Fake HttpStreamRequest that simply records calls to SetPriority()
14148// and vends FakeStreams with its current priority.
[email protected]bf828982013-08-14 18:01:4714149class FakeStreamRequest : public HttpStreamRequest,
14150 public base::SupportsWeakPtr<FakeStreamRequest> {
14151 public:
[email protected]e86839fd2013-08-14 18:29:0314152 FakeStreamRequest(RequestPriority priority,
14153 HttpStreamRequest::Delegate* delegate)
14154 : priority_(priority),
[email protected]831e4a32013-11-14 02:14:4414155 delegate_(delegate),
14156 websocket_stream_create_helper_(NULL) {}
14157
14158 FakeStreamRequest(RequestPriority priority,
14159 HttpStreamRequest::Delegate* delegate,
14160 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
14161 : priority_(priority),
14162 delegate_(delegate),
14163 websocket_stream_create_helper_(create_helper) {}
[email protected]e86839fd2013-08-14 18:29:0314164
dchengb03027d2014-10-21 12:00:2014165 ~FakeStreamRequest() override {}
[email protected]bf828982013-08-14 18:01:4714166
14167 RequestPriority priority() const { return priority_; }
14168
[email protected]831e4a32013-11-14 02:14:4414169 const WebSocketHandshakeStreamBase::CreateHelper*
14170 websocket_stream_create_helper() const {
14171 return websocket_stream_create_helper_;
14172 }
14173
[email protected]e86839fd2013-08-14 18:29:0314174 // Create a new FakeStream and pass it to the request's
14175 // delegate. Returns a weak pointer to the FakeStream.
14176 base::WeakPtr<FakeStream> FinishStreamRequest() {
14177 FakeStream* fake_stream = new FakeStream(priority_);
14178 // Do this before calling OnStreamReady() as OnStreamReady() may
14179 // immediately delete |fake_stream|.
14180 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
14181 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
14182 return weak_stream;
14183 }
14184
dchengb03027d2014-10-21 12:00:2014185 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
[email protected]bf828982013-08-14 18:01:4714186 ADD_FAILURE();
14187 return ERR_UNEXPECTED;
14188 }
14189
dchengb03027d2014-10-21 12:00:2014190 LoadState GetLoadState() const override {
[email protected]bf828982013-08-14 18:01:4714191 ADD_FAILURE();
14192 return LoadState();
14193 }
14194
dchengb03027d2014-10-21 12:00:2014195 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]bf828982013-08-14 18:01:4714196
dchengb03027d2014-10-21 12:00:2014197 bool was_npn_negotiated() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714198
dchengb03027d2014-10-21 12:00:2014199 NextProto protocol_negotiated() const override { return kProtoUnknown; }
[email protected]bf828982013-08-14 18:01:4714200
dchengb03027d2014-10-21 12:00:2014201 bool using_spdy() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714202
ttuttle1f2d7e92015-04-28 16:17:4714203 const ConnectionAttempts& connection_attempts() const override {
14204 static ConnectionAttempts no_attempts;
14205 return no_attempts;
14206 }
14207
[email protected]bf828982013-08-14 18:01:4714208 private:
14209 RequestPriority priority_;
[email protected]e86839fd2013-08-14 18:29:0314210 HttpStreamRequest::Delegate* const delegate_;
[email protected]831e4a32013-11-14 02:14:4414211 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
[email protected]bf828982013-08-14 18:01:4714212
14213 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
14214};
14215
14216// Fake HttpStreamFactory that vends FakeStreamRequests.
14217class FakeStreamFactory : public HttpStreamFactory {
14218 public:
14219 FakeStreamFactory() {}
dchengb03027d2014-10-21 12:00:2014220 ~FakeStreamFactory() override {}
[email protected]bf828982013-08-14 18:01:4714221
14222 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
14223 // RequestStream() (which may be NULL if it was destroyed already).
14224 base::WeakPtr<FakeStreamRequest> last_stream_request() {
14225 return last_stream_request_;
14226 }
14227
dchengb03027d2014-10-21 12:00:2014228 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
14229 RequestPriority priority,
14230 const SSLConfig& server_ssl_config,
14231 const SSLConfig& proxy_ssl_config,
14232 HttpStreamRequest::Delegate* delegate,
14233 const BoundNetLog& net_log) override {
[email protected]e86839fd2013-08-14 18:29:0314234 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
[email protected]bf828982013-08-14 18:01:4714235 last_stream_request_ = fake_request->AsWeakPtr();
14236 return fake_request;
14237 }
14238
dchengb03027d2014-10-21 12:00:2014239 HttpStreamRequest* RequestWebSocketHandshakeStream(
[email protected]bf828982013-08-14 18:01:4714240 const HttpRequestInfo& info,
14241 RequestPriority priority,
14242 const SSLConfig& server_ssl_config,
14243 const SSLConfig& proxy_ssl_config,
14244 HttpStreamRequest::Delegate* delegate,
[email protected]467086b2013-11-12 08:19:4614245 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
mostynbba063d6032014-10-09 11:01:1314246 const BoundNetLog& net_log) override {
[email protected]831e4a32013-11-14 02:14:4414247 FakeStreamRequest* fake_request =
14248 new FakeStreamRequest(priority, delegate, create_helper);
14249 last_stream_request_ = fake_request->AsWeakPtr();
14250 return fake_request;
[email protected]bf828982013-08-14 18:01:4714251 }
14252
dchengb03027d2014-10-21 12:00:2014253 void PreconnectStreams(int num_streams,
14254 const HttpRequestInfo& info,
dchengb03027d2014-10-21 12:00:2014255 const SSLConfig& server_ssl_config,
14256 const SSLConfig& proxy_ssl_config) override {
[email protected]bf828982013-08-14 18:01:4714257 ADD_FAILURE();
14258 }
14259
dchengb03027d2014-10-21 12:00:2014260 const HostMappingRules* GetHostMappingRules() const override {
[email protected]bf828982013-08-14 18:01:4714261 ADD_FAILURE();
14262 return NULL;
14263 }
14264
14265 private:
14266 base::WeakPtr<FakeStreamRequest> last_stream_request_;
14267
14268 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
14269};
14270
Adam Rice425cf122015-01-19 06:18:2414271// TODO(ricea): Maybe unify this with the one in
14272// url_request_http_job_unittest.cc ?
14273class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
14274 public:
14275 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection,
14276 bool using_proxy)
14277 : state_(connection.release(), using_proxy) {}
14278
14279 // Fake implementation of HttpStreamBase methods.
14280 // This ends up being quite "real" because this object has to really send data
14281 // on the mock socket. It might be easier to use the real implementation, but
14282 // the fact that the WebSocket code is not compiled on iOS makes that
14283 // difficult.
14284 int InitializeStream(const HttpRequestInfo* request_info,
14285 RequestPriority priority,
14286 const BoundNetLog& net_log,
14287 const CompletionCallback& callback) override {
14288 state_.Initialize(request_info, priority, net_log, callback);
14289 return OK;
14290 }
14291
14292 int SendRequest(const HttpRequestHeaders& request_headers,
14293 HttpResponseInfo* response,
14294 const CompletionCallback& callback) override {
14295 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
14296 response, callback);
14297 }
14298
14299 int ReadResponseHeaders(const CompletionCallback& callback) override {
14300 return parser()->ReadResponseHeaders(callback);
14301 }
14302
14303 int ReadResponseBody(IOBuffer* buf,
14304 int buf_len,
14305 const CompletionCallback& callback) override {
14306 NOTREACHED();
14307 return ERR_IO_PENDING;
14308 }
14309
14310 void Close(bool not_reusable) override {
14311 if (parser())
14312 parser()->Close(true);
14313 }
14314
14315 bool IsResponseBodyComplete() const override {
14316 NOTREACHED();
14317 return false;
14318 }
14319
Adam Rice425cf122015-01-19 06:18:2414320 bool IsConnectionReused() const override {
14321 NOTREACHED();
14322 return false;
14323 }
14324 void SetConnectionReused() override { NOTREACHED(); }
14325
mmenkebd84c392015-09-02 14:12:3414326 bool CanReuseConnection() const override { return false; }
Adam Rice425cf122015-01-19 06:18:2414327
sclittle4de1bab92015-09-22 21:28:2414328 int64_t GetTotalReceivedBytes() const override {
Adam Rice425cf122015-01-19 06:18:2414329 NOTREACHED();
14330 return 0;
14331 }
14332
sclittlebe1ccf62015-09-02 19:40:3614333 int64_t GetTotalSentBytes() const override {
14334 NOTREACHED();
14335 return 0;
14336 }
14337
Adam Rice425cf122015-01-19 06:18:2414338 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
14339 NOTREACHED();
14340 return false;
14341 }
14342
Adam Ricecb76ac62015-02-20 05:33:2514343 void GetSSLInfo(SSLInfo* ssl_info) override {}
Adam Rice425cf122015-01-19 06:18:2414344
14345 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
14346 NOTREACHED();
14347 }
14348
ttuttled9dbc652015-09-29 20:00:5914349 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
14350
Adam Rice425cf122015-01-19 06:18:2414351 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
14352
14353 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
14354
14355 UploadProgress GetUploadProgress() const override {
14356 NOTREACHED();
14357 return UploadProgress();
14358 }
14359
14360 HttpStream* RenewStreamForAuth() override {
14361 NOTREACHED();
14362 return nullptr;
14363 }
14364
14365 // Fake implementation of WebSocketHandshakeStreamBase method(s)
14366 scoped_ptr<WebSocketStream> Upgrade() override {
14367 NOTREACHED();
14368 return scoped_ptr<WebSocketStream>();
14369 }
14370
14371 private:
14372 HttpStreamParser* parser() const { return state_.parser(); }
14373 HttpBasicState state_;
14374
14375 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
14376};
14377
[email protected]831e4a32013-11-14 02:14:4414378// TODO(yhirano): Split this class out into a net/websockets file, if it is
14379// worth doing.
14380class FakeWebSocketStreamCreateHelper :
14381 public WebSocketHandshakeStreamBase::CreateHelper {
14382 public:
dchengb03027d2014-10-21 12:00:2014383 WebSocketHandshakeStreamBase* CreateBasicStream(
[email protected]7e841a52013-11-22 09:04:2114384 scoped_ptr<ClientSocketHandle> connection,
mostynbba063d6032014-10-09 11:01:1314385 bool using_proxy) override {
Adam Rice425cf122015-01-19 06:18:2414386 return new FakeWebSocketBasicHandshakeStream(connection.Pass(),
14387 using_proxy);
[email protected]831e4a32013-11-14 02:14:4414388 }
14389
dchengb03027d2014-10-21 12:00:2014390 WebSocketHandshakeStreamBase* CreateSpdyStream(
[email protected]831e4a32013-11-14 02:14:4414391 const base::WeakPtr<SpdySession>& session,
mostynbba063d6032014-10-09 11:01:1314392 bool use_relative_url) override {
[email protected]831e4a32013-11-14 02:14:4414393 NOTREACHED();
14394 return NULL;
14395 };
14396
dchengb03027d2014-10-21 12:00:2014397 ~FakeWebSocketStreamCreateHelper() override {}
[email protected]831e4a32013-11-14 02:14:4414398
14399 virtual scoped_ptr<WebSocketStream> Upgrade() {
14400 NOTREACHED();
14401 return scoped_ptr<WebSocketStream>();
14402 }
14403};
14404
[email protected]bf828982013-08-14 18:01:4714405} // namespace
14406
14407// Make sure that HttpNetworkTransaction passes on its priority to its
14408// stream request on start.
14409TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
mmenkee65e7af2015-10-13 17:16:4214410 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14411 HttpNetworkSessionPeer peer(session.get());
[email protected]bf828982013-08-14 18:01:4714412 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414413 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714414
dcheng48459ac22014-08-26 00:46:4114415 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714416
14417 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
14418
14419 HttpRequestInfo request;
14420 TestCompletionCallback callback;
14421 EXPECT_EQ(ERR_IO_PENDING,
14422 trans.Start(&request, callback.callback(), BoundNetLog()));
14423
14424 base::WeakPtr<FakeStreamRequest> fake_request =
14425 fake_factory->last_stream_request();
14426 ASSERT_TRUE(fake_request != NULL);
14427 EXPECT_EQ(LOW, fake_request->priority());
14428}
14429
14430// Make sure that HttpNetworkTransaction passes on its priority
14431// updates to its stream request.
14432TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
mmenkee65e7af2015-10-13 17:16:4214433 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14434 HttpNetworkSessionPeer peer(session.get());
[email protected]bf828982013-08-14 18:01:4714435 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414436 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714437
dcheng48459ac22014-08-26 00:46:4114438 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714439
14440 HttpRequestInfo request;
14441 TestCompletionCallback callback;
14442 EXPECT_EQ(ERR_IO_PENDING,
14443 trans.Start(&request, callback.callback(), BoundNetLog()));
14444
14445 base::WeakPtr<FakeStreamRequest> fake_request =
14446 fake_factory->last_stream_request();
14447 ASSERT_TRUE(fake_request != NULL);
14448 EXPECT_EQ(LOW, fake_request->priority());
14449
14450 trans.SetPriority(LOWEST);
14451 ASSERT_TRUE(fake_request != NULL);
14452 EXPECT_EQ(LOWEST, fake_request->priority());
14453}
14454
[email protected]e86839fd2013-08-14 18:29:0314455// Make sure that HttpNetworkTransaction passes on its priority
14456// updates to its stream.
14457TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
mmenkee65e7af2015-10-13 17:16:4214458 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14459 HttpNetworkSessionPeer peer(session.get());
[email protected]e86839fd2013-08-14 18:29:0314460 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414461 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]e86839fd2013-08-14 18:29:0314462
dcheng48459ac22014-08-26 00:46:4114463 HttpNetworkTransaction trans(LOW, session.get());
[email protected]e86839fd2013-08-14 18:29:0314464
14465 HttpRequestInfo request;
14466 TestCompletionCallback callback;
14467 EXPECT_EQ(ERR_IO_PENDING,
14468 trans.Start(&request, callback.callback(), BoundNetLog()));
14469
14470 base::WeakPtr<FakeStreamRequest> fake_request =
14471 fake_factory->last_stream_request();
14472 ASSERT_TRUE(fake_request != NULL);
14473 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
14474 ASSERT_TRUE(fake_stream != NULL);
14475 EXPECT_EQ(LOW, fake_stream->priority());
14476
14477 trans.SetPriority(LOWEST);
14478 EXPECT_EQ(LOWEST, fake_stream->priority());
14479}
14480
[email protected]831e4a32013-11-14 02:14:4414481TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
14482 // The same logic needs to be tested for both ws: and wss: schemes, but this
14483 // test is already parameterised on NextProto, so it uses a loop to verify
14484 // that the different schemes work.
bncce36dca22015-04-21 22:11:2314485 std::string test_cases[] = {"ws://www.example.org/",
14486 "wss://www.example.org/"};
[email protected]831e4a32013-11-14 02:14:4414487 for (size_t i = 0; i < arraysize(test_cases); ++i) {
mmenkee65e7af2015-10-13 17:16:4214488 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14489 HttpNetworkSessionPeer peer(session.get());
[email protected]831e4a32013-11-14 02:14:4414490 FakeStreamFactory* fake_factory = new FakeStreamFactory();
14491 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
[email protected]0191b51c2013-11-18 10:55:2314492 peer.SetHttpStreamFactoryForWebSocket(
[email protected]831e4a32013-11-14 02:14:4414493 scoped_ptr<HttpStreamFactory>(fake_factory));
14494
dcheng48459ac22014-08-26 00:46:4114495 HttpNetworkTransaction trans(LOW, session.get());
[email protected]831e4a32013-11-14 02:14:4414496 trans.SetWebSocketHandshakeStreamCreateHelper(
14497 &websocket_stream_create_helper);
14498
14499 HttpRequestInfo request;
14500 TestCompletionCallback callback;
14501 request.method = "GET";
14502 request.url = GURL(test_cases[i]);
14503
14504 EXPECT_EQ(ERR_IO_PENDING,
14505 trans.Start(&request, callback.callback(), BoundNetLog()));
14506
14507 base::WeakPtr<FakeStreamRequest> fake_request =
14508 fake_factory->last_stream_request();
14509 ASSERT_TRUE(fake_request != NULL);
14510 EXPECT_EQ(&websocket_stream_create_helper,
14511 fake_request->websocket_stream_create_helper());
14512 }
14513}
14514
[email protected]043b68c82013-08-22 23:41:5214515// Tests that when a used socket is returned to the SSL socket pool, it's closed
14516// if the transport socket pool is stalled on the global socket limit.
14517TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
14518 ClientSocketPoolManager::set_max_sockets_per_group(
14519 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14520 ClientSocketPoolManager::set_max_sockets_per_pool(
14521 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14522
14523 // Set up SSL request.
14524
14525 HttpRequestInfo ssl_request;
14526 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2314527 ssl_request.url = GURL("https://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214528
14529 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2314530 MockWrite(
14531 "GET / HTTP/1.1\r\n"
14532 "Host: www.example.org\r\n"
14533 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214534 };
14535 MockRead ssl_reads[] = {
14536 MockRead("HTTP/1.1 200 OK\r\n"),
14537 MockRead("Content-Length: 11\r\n\r\n"),
14538 MockRead("hello world"),
14539 MockRead(SYNCHRONOUS, OK),
14540 };
14541 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
14542 ssl_writes, arraysize(ssl_writes));
14543 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
14544
14545 SSLSocketDataProvider ssl(ASYNC, OK);
14546 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14547
14548 // Set up HTTP request.
14549
14550 HttpRequestInfo http_request;
14551 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2314552 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214553
14554 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2314555 MockWrite(
14556 "GET / HTTP/1.1\r\n"
14557 "Host: www.example.org\r\n"
14558 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214559 };
14560 MockRead http_reads[] = {
14561 MockRead("HTTP/1.1 200 OK\r\n"),
14562 MockRead("Content-Length: 7\r\n\r\n"),
14563 MockRead("falafel"),
14564 MockRead(SYNCHRONOUS, OK),
14565 };
14566 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
14567 http_writes, arraysize(http_writes));
14568 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14569
mmenkee65e7af2015-10-13 17:16:4214570 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5214571
14572 // Start the SSL request.
14573 TestCompletionCallback ssl_callback;
14574 scoped_ptr<HttpTransaction> ssl_trans(
14575 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14576 ASSERT_EQ(ERR_IO_PENDING,
14577 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
14578 BoundNetLog()));
14579
14580 // Start the HTTP request. Pool should stall.
14581 TestCompletionCallback http_callback;
14582 scoped_ptr<HttpTransaction> http_trans(
14583 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14584 ASSERT_EQ(ERR_IO_PENDING,
14585 http_trans->Start(&http_request, http_callback.callback(),
14586 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4114587 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214588
14589 // Wait for response from SSL request.
14590 ASSERT_EQ(OK, ssl_callback.WaitForResult());
14591 std::string response_data;
14592 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
14593 EXPECT_EQ("hello world", response_data);
14594
14595 // The SSL socket should automatically be closed, so the HTTP request can
14596 // start.
dcheng48459ac22014-08-26 00:46:4114597 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
14598 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214599
14600 // The HTTP request can now complete.
14601 ASSERT_EQ(OK, http_callback.WaitForResult());
14602 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
14603 EXPECT_EQ("falafel", response_data);
14604
dcheng48459ac22014-08-26 00:46:4114605 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214606}
14607
14608// Tests that when a SSL connection is established but there's no corresponding
14609// request that needs it, the new socket is closed if the transport socket pool
14610// is stalled on the global socket limit.
14611TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
14612 ClientSocketPoolManager::set_max_sockets_per_group(
14613 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14614 ClientSocketPoolManager::set_max_sockets_per_pool(
14615 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14616
14617 // Set up an ssl request.
14618
14619 HttpRequestInfo ssl_request;
14620 ssl_request.method = "GET";
14621 ssl_request.url = GURL("https://www.foopy.com/");
14622
14623 // No data will be sent on the SSL socket.
14624 StaticSocketDataProvider ssl_data;
14625 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
14626
14627 SSLSocketDataProvider ssl(ASYNC, OK);
14628 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14629
14630 // Set up HTTP request.
14631
14632 HttpRequestInfo http_request;
14633 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2314634 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214635
14636 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2314637 MockWrite(
14638 "GET / HTTP/1.1\r\n"
14639 "Host: www.example.org\r\n"
14640 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214641 };
14642 MockRead http_reads[] = {
14643 MockRead("HTTP/1.1 200 OK\r\n"),
14644 MockRead("Content-Length: 7\r\n\r\n"),
14645 MockRead("falafel"),
14646 MockRead(SYNCHRONOUS, OK),
14647 };
14648 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
14649 http_writes, arraysize(http_writes));
14650 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14651
mmenkee65e7af2015-10-13 17:16:4214652 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5214653
14654 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
14655 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2914656 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
14657 SSLConfig ssl_config;
[email protected]043b68c82013-08-22 23:41:5214658 session->ssl_config_service()->GetSSLConfig(&ssl_config);
mmenked1205bd3972015-07-15 22:26:3514659 http_stream_factory->PreconnectStreams(1, ssl_request, ssl_config,
14660 ssl_config);
dcheng48459ac22014-08-26 00:46:4114661 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214662
14663 // Start the HTTP request. Pool should stall.
14664 TestCompletionCallback http_callback;
14665 scoped_ptr<HttpTransaction> http_trans(
14666 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14667 ASSERT_EQ(ERR_IO_PENDING,
14668 http_trans->Start(&http_request, http_callback.callback(),
14669 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4114670 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214671
14672 // The SSL connection will automatically be closed once the connection is
14673 // established, to let the HTTP request start.
14674 ASSERT_EQ(OK, http_callback.WaitForResult());
14675 std::string response_data;
14676 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
14677 EXPECT_EQ("falafel", response_data);
14678
dcheng48459ac22014-08-26 00:46:4114679 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214680}
14681
[email protected]02d74a02014-04-23 18:10:5414682TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2214683 std::vector<scoped_ptr<UploadElementReader>> element_readers;
14684 element_readers.push_back(
14685 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
14686 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5414687
14688 HttpRequestInfo request;
14689 request.method = "POST";
14690 request.url = GURL("http://www.foo.com/");
14691 request.upload_data_stream = &upload_data_stream;
14692 request.load_flags = 0;
14693
mmenkee65e7af2015-10-13 17:16:4214694 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414695 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114696 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414697 // Send headers successfully, but get an error while sending the body.
14698 MockWrite data_writes[] = {
14699 MockWrite("POST / HTTP/1.1\r\n"
14700 "Host: www.foo.com\r\n"
14701 "Connection: keep-alive\r\n"
14702 "Content-Length: 3\r\n\r\n"),
14703 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14704 };
14705
14706 MockRead data_reads[] = {
14707 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14708 MockRead("hello world"),
14709 MockRead(SYNCHRONOUS, OK),
14710 };
14711 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14712 arraysize(data_writes));
14713 session_deps_.socket_factory->AddSocketDataProvider(&data);
14714
14715 TestCompletionCallback callback;
14716
14717 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14718 EXPECT_EQ(ERR_IO_PENDING, rv);
14719
14720 rv = callback.WaitForResult();
14721 EXPECT_EQ(OK, rv);
14722
14723 const HttpResponseInfo* response = trans->GetResponseInfo();
14724 ASSERT_TRUE(response != NULL);
14725
14726 EXPECT_TRUE(response->headers.get() != NULL);
14727 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14728
14729 std::string response_data;
14730 rv = ReadTransaction(trans.get(), &response_data);
14731 EXPECT_EQ(OK, rv);
14732 EXPECT_EQ("hello world", response_data);
14733}
14734
14735// This test makes sure the retry logic doesn't trigger when reading an error
14736// response from a server that rejected a POST with a CONNECTION_RESET.
14737TEST_P(HttpNetworkTransactionTest,
14738 PostReadsErrorResponseAfterResetOnReusedSocket) {
mmenkee65e7af2015-10-13 17:16:4214739 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414740 MockWrite data_writes[] = {
14741 MockWrite("GET / HTTP/1.1\r\n"
14742 "Host: www.foo.com\r\n"
14743 "Connection: keep-alive\r\n\r\n"),
14744 MockWrite("POST / HTTP/1.1\r\n"
14745 "Host: www.foo.com\r\n"
14746 "Connection: keep-alive\r\n"
14747 "Content-Length: 3\r\n\r\n"),
14748 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14749 };
14750
14751 MockRead data_reads[] = {
14752 MockRead("HTTP/1.1 200 Peachy\r\n"
14753 "Content-Length: 14\r\n\r\n"),
14754 MockRead("first response"),
14755 MockRead("HTTP/1.1 400 Not OK\r\n"
14756 "Content-Length: 15\r\n\r\n"),
14757 MockRead("second response"),
14758 MockRead(SYNCHRONOUS, OK),
14759 };
14760 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14761 arraysize(data_writes));
14762 session_deps_.socket_factory->AddSocketDataProvider(&data);
14763
14764 TestCompletionCallback callback;
14765 HttpRequestInfo request1;
14766 request1.method = "GET";
14767 request1.url = GURL("http://www.foo.com/");
14768 request1.load_flags = 0;
14769
14770 scoped_ptr<HttpTransaction> trans1(
dcheng48459ac22014-08-26 00:46:4114771 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414772 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
14773 EXPECT_EQ(ERR_IO_PENDING, rv);
14774
14775 rv = callback.WaitForResult();
14776 EXPECT_EQ(OK, rv);
14777
14778 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
14779 ASSERT_TRUE(response1 != NULL);
14780
14781 EXPECT_TRUE(response1->headers.get() != NULL);
14782 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
14783
14784 std::string response_data1;
14785 rv = ReadTransaction(trans1.get(), &response_data1);
14786 EXPECT_EQ(OK, rv);
14787 EXPECT_EQ("first response", response_data1);
14788 // Delete the transaction to release the socket back into the socket pool.
14789 trans1.reset();
14790
olli.raula6df48b2a2015-11-26 07:40:2214791 std::vector<scoped_ptr<UploadElementReader>> element_readers;
14792 element_readers.push_back(
14793 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
14794 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5414795
14796 HttpRequestInfo request2;
14797 request2.method = "POST";
14798 request2.url = GURL("http://www.foo.com/");
14799 request2.upload_data_stream = &upload_data_stream;
14800 request2.load_flags = 0;
14801
14802 scoped_ptr<HttpTransaction> trans2(
dcheng48459ac22014-08-26 00:46:4114803 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414804 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
14805 EXPECT_EQ(ERR_IO_PENDING, rv);
14806
14807 rv = callback.WaitForResult();
14808 EXPECT_EQ(OK, rv);
14809
14810 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
14811 ASSERT_TRUE(response2 != NULL);
14812
14813 EXPECT_TRUE(response2->headers.get() != NULL);
14814 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
14815
14816 std::string response_data2;
14817 rv = ReadTransaction(trans2.get(), &response_data2);
14818 EXPECT_EQ(OK, rv);
14819 EXPECT_EQ("second response", response_data2);
14820}
14821
14822TEST_P(HttpNetworkTransactionTest,
14823 PostReadsErrorResponseAfterResetPartialBodySent) {
olli.raula6df48b2a2015-11-26 07:40:2214824 std::vector<scoped_ptr<UploadElementReader>> element_readers;
14825 element_readers.push_back(
14826 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
14827 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5414828
14829 HttpRequestInfo request;
14830 request.method = "POST";
14831 request.url = GURL("http://www.foo.com/");
14832 request.upload_data_stream = &upload_data_stream;
14833 request.load_flags = 0;
14834
mmenkee65e7af2015-10-13 17:16:4214835 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414836 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114837 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414838 // Send headers successfully, but get an error while sending the body.
14839 MockWrite data_writes[] = {
14840 MockWrite("POST / HTTP/1.1\r\n"
14841 "Host: www.foo.com\r\n"
14842 "Connection: keep-alive\r\n"
14843 "Content-Length: 3\r\n\r\n"
14844 "fo"),
14845 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14846 };
14847
14848 MockRead data_reads[] = {
14849 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14850 MockRead("hello world"),
14851 MockRead(SYNCHRONOUS, OK),
14852 };
14853 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14854 arraysize(data_writes));
14855 session_deps_.socket_factory->AddSocketDataProvider(&data);
14856
14857 TestCompletionCallback callback;
14858
14859 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14860 EXPECT_EQ(ERR_IO_PENDING, rv);
14861
14862 rv = callback.WaitForResult();
14863 EXPECT_EQ(OK, rv);
14864
14865 const HttpResponseInfo* response = trans->GetResponseInfo();
14866 ASSERT_TRUE(response != NULL);
14867
14868 EXPECT_TRUE(response->headers.get() != NULL);
14869 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14870
14871 std::string response_data;
14872 rv = ReadTransaction(trans.get(), &response_data);
14873 EXPECT_EQ(OK, rv);
14874 EXPECT_EQ("hello world", response_data);
14875}
14876
14877// This tests the more common case than the previous test, where headers and
14878// body are not merged into a single request.
14879TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0714880 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5414881
14882 HttpRequestInfo request;
14883 request.method = "POST";
14884 request.url = GURL("http://www.foo.com/");
14885 request.upload_data_stream = &upload_data_stream;
14886 request.load_flags = 0;
14887
mmenkee65e7af2015-10-13 17:16:4214888 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414889 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114890 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414891 // Send headers successfully, but get an error while sending the body.
14892 MockWrite data_writes[] = {
14893 MockWrite("POST / HTTP/1.1\r\n"
14894 "Host: www.foo.com\r\n"
14895 "Connection: keep-alive\r\n"
14896 "Transfer-Encoding: chunked\r\n\r\n"),
14897 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14898 };
14899
14900 MockRead data_reads[] = {
14901 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14902 MockRead("hello world"),
14903 MockRead(SYNCHRONOUS, OK),
14904 };
14905 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14906 arraysize(data_writes));
14907 session_deps_.socket_factory->AddSocketDataProvider(&data);
14908
14909 TestCompletionCallback callback;
14910
14911 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14912 EXPECT_EQ(ERR_IO_PENDING, rv);
14913 // Make sure the headers are sent before adding a chunk. This ensures that
14914 // they can't be merged with the body in a single send. Not currently
14915 // necessary since a chunked body is never merged with headers, but this makes
14916 // the test more future proof.
14917 base::RunLoop().RunUntilIdle();
14918
mmenkecbc2b712014-10-09 20:29:0714919 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5414920
14921 rv = callback.WaitForResult();
14922 EXPECT_EQ(OK, rv);
14923
14924 const HttpResponseInfo* response = trans->GetResponseInfo();
14925 ASSERT_TRUE(response != NULL);
14926
14927 EXPECT_TRUE(response->headers.get() != NULL);
14928 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14929
14930 std::string response_data;
14931 rv = ReadTransaction(trans.get(), &response_data);
14932 EXPECT_EQ(OK, rv);
14933 EXPECT_EQ("hello world", response_data);
14934}
14935
14936TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
olli.raula6df48b2a2015-11-26 07:40:2214937 std::vector<scoped_ptr<UploadElementReader>> element_readers;
14938 element_readers.push_back(
14939 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
14940 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5414941
14942 HttpRequestInfo request;
14943 request.method = "POST";
14944 request.url = GURL("http://www.foo.com/");
14945 request.upload_data_stream = &upload_data_stream;
14946 request.load_flags = 0;
14947
mmenkee65e7af2015-10-13 17:16:4214948 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414949 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114950 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414951
14952 MockWrite data_writes[] = {
14953 MockWrite("POST / HTTP/1.1\r\n"
14954 "Host: www.foo.com\r\n"
14955 "Connection: keep-alive\r\n"
14956 "Content-Length: 3\r\n\r\n"),
14957 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14958 };
14959
14960 MockRead data_reads[] = {
14961 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14962 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14963 MockRead("hello world"),
14964 MockRead(SYNCHRONOUS, OK),
14965 };
14966 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14967 arraysize(data_writes));
14968 session_deps_.socket_factory->AddSocketDataProvider(&data);
14969
14970 TestCompletionCallback callback;
14971
14972 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14973 EXPECT_EQ(ERR_IO_PENDING, rv);
14974
14975 rv = callback.WaitForResult();
14976 EXPECT_EQ(OK, rv);
14977
14978 const HttpResponseInfo* response = trans->GetResponseInfo();
14979 ASSERT_TRUE(response != NULL);
14980
14981 EXPECT_TRUE(response->headers.get() != NULL);
14982 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14983
14984 std::string response_data;
14985 rv = ReadTransaction(trans.get(), &response_data);
14986 EXPECT_EQ(OK, rv);
14987 EXPECT_EQ("hello world", response_data);
14988}
14989
14990TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2214991 std::vector<scoped_ptr<UploadElementReader>> element_readers;
14992 element_readers.push_back(
14993 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
14994 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5414995
14996 HttpRequestInfo request;
14997 request.method = "POST";
14998 request.url = GURL("http://www.foo.com/");
14999 request.upload_data_stream = &upload_data_stream;
15000 request.load_flags = 0;
15001
mmenkee65e7af2015-10-13 17:16:4215002 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415003 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115004 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415005 // Send headers successfully, but get an error while sending the body.
15006 MockWrite data_writes[] = {
15007 MockWrite("POST / HTTP/1.1\r\n"
15008 "Host: www.foo.com\r\n"
15009 "Connection: keep-alive\r\n"
15010 "Content-Length: 3\r\n\r\n"),
15011 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15012 };
15013
15014 MockRead data_reads[] = {
15015 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
15016 MockRead("hello world"),
15017 MockRead(SYNCHRONOUS, OK),
15018 };
15019 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15020 arraysize(data_writes));
15021 session_deps_.socket_factory->AddSocketDataProvider(&data);
15022
15023 TestCompletionCallback callback;
15024
15025 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15026 EXPECT_EQ(ERR_IO_PENDING, rv);
15027
15028 rv = callback.WaitForResult();
15029 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415030}
15031
15032TEST_P(HttpNetworkTransactionTest,
15033 PostIgnoresNonErrorResponseAfterResetAnd100) {
olli.raula6df48b2a2015-11-26 07:40:2215034 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15035 element_readers.push_back(
15036 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15037 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415038
15039 HttpRequestInfo request;
15040 request.method = "POST";
15041 request.url = GURL("http://www.foo.com/");
15042 request.upload_data_stream = &upload_data_stream;
15043 request.load_flags = 0;
15044
mmenkee65e7af2015-10-13 17:16:4215045 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415046 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115047 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415048 // Send headers successfully, but get an error while sending the body.
15049 MockWrite data_writes[] = {
15050 MockWrite("POST / HTTP/1.1\r\n"
15051 "Host: www.foo.com\r\n"
15052 "Connection: keep-alive\r\n"
15053 "Content-Length: 3\r\n\r\n"),
15054 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15055 };
15056
15057 MockRead data_reads[] = {
15058 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
15059 MockRead("HTTP/1.0 302 Redirect\r\n"),
15060 MockRead("Location: http://somewhere-else.com/\r\n"),
15061 MockRead("Content-Length: 0\r\n\r\n"),
15062 MockRead(SYNCHRONOUS, OK),
15063 };
15064 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15065 arraysize(data_writes));
15066 session_deps_.socket_factory->AddSocketDataProvider(&data);
15067
15068 TestCompletionCallback callback;
15069
15070 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15071 EXPECT_EQ(ERR_IO_PENDING, rv);
15072
15073 rv = callback.WaitForResult();
15074 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415075}
15076
15077TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215078 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15079 element_readers.push_back(
15080 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15081 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415082
15083 HttpRequestInfo request;
15084 request.method = "POST";
15085 request.url = GURL("http://www.foo.com/");
15086 request.upload_data_stream = &upload_data_stream;
15087 request.load_flags = 0;
15088
mmenkee65e7af2015-10-13 17:16:4215089 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415090 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115091 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415092 // Send headers successfully, but get an error while sending the body.
15093 MockWrite data_writes[] = {
15094 MockWrite("POST / HTTP/1.1\r\n"
15095 "Host: www.foo.com\r\n"
15096 "Connection: keep-alive\r\n"
15097 "Content-Length: 3\r\n\r\n"),
15098 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15099 };
15100
15101 MockRead data_reads[] = {
15102 MockRead("HTTP 0.9 rocks!"),
15103 MockRead(SYNCHRONOUS, OK),
15104 };
15105 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15106 arraysize(data_writes));
15107 session_deps_.socket_factory->AddSocketDataProvider(&data);
15108
15109 TestCompletionCallback callback;
15110
15111 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15112 EXPECT_EQ(ERR_IO_PENDING, rv);
15113
15114 rv = callback.WaitForResult();
15115 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415116}
15117
15118TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215119 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15120 element_readers.push_back(
15121 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15122 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415123
15124 HttpRequestInfo request;
15125 request.method = "POST";
15126 request.url = GURL("http://www.foo.com/");
15127 request.upload_data_stream = &upload_data_stream;
15128 request.load_flags = 0;
15129
mmenkee65e7af2015-10-13 17:16:4215130 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415131 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115132 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415133 // Send headers successfully, but get an error while sending the body.
15134 MockWrite data_writes[] = {
15135 MockWrite("POST / HTTP/1.1\r\n"
15136 "Host: www.foo.com\r\n"
15137 "Connection: keep-alive\r\n"
15138 "Content-Length: 3\r\n\r\n"),
15139 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15140 };
15141
15142 MockRead data_reads[] = {
15143 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
15144 MockRead(SYNCHRONOUS, OK),
15145 };
15146 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15147 arraysize(data_writes));
15148 session_deps_.socket_factory->AddSocketDataProvider(&data);
15149
15150 TestCompletionCallback callback;
15151
15152 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15153 EXPECT_EQ(ERR_IO_PENDING, rv);
15154
15155 rv = callback.WaitForResult();
15156 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415157}
15158
Adam Rice425cf122015-01-19 06:18:2415159// Verify that proxy headers are not sent to the destination server when
15160// establishing a tunnel for a secure WebSocket connection.
15161TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
15162 HttpRequestInfo request;
15163 request.method = "GET";
bncce36dca22015-04-21 22:11:2315164 request.url = GURL("wss://www.example.org/");
Adam Rice425cf122015-01-19 06:18:2415165 AddWebSocketHeaders(&request.extra_headers);
15166
15167 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:0315168 session_deps_.proxy_service =
15169 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
Adam Rice425cf122015-01-19 06:18:2415170
mmenkee65e7af2015-10-13 17:16:4215171 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2415172
15173 // Since a proxy is configured, try to establish a tunnel.
15174 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1715175 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15176 "Host: www.example.org:443\r\n"
15177 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415178
15179 // After calling trans->RestartWithAuth(), this is the request we should
15180 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1715181 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15182 "Host: www.example.org:443\r\n"
15183 "Proxy-Connection: keep-alive\r\n"
15184 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415185
rsleevidb16bb02015-11-12 23:47:1715186 MockWrite("GET / HTTP/1.1\r\n"
15187 "Host: www.example.org\r\n"
15188 "Connection: Upgrade\r\n"
15189 "Upgrade: websocket\r\n"
15190 "Origin: http://www.example.org\r\n"
15191 "Sec-WebSocket-Version: 13\r\n"
15192 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415193 };
15194
15195 // The proxy responds to the connect with a 407, using a persistent
15196 // connection.
15197 MockRead data_reads[] = {
15198 // No credentials.
15199 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
15200 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
mmenkee71e15332015-10-07 16:39:5415201 MockRead("Content-Length: 0\r\n"),
15202 MockRead("Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415203
15204 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15205
15206 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15207 MockRead("Upgrade: websocket\r\n"),
15208 MockRead("Connection: Upgrade\r\n"),
15209 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15210 };
15211
15212 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15213 arraysize(data_writes));
15214 session_deps_.socket_factory->AddSocketDataProvider(&data);
15215 SSLSocketDataProvider ssl(ASYNC, OK);
15216 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15217
15218 scoped_ptr<HttpTransaction> trans(
15219 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15220 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15221 trans->SetWebSocketHandshakeStreamCreateHelper(
15222 &websocket_stream_create_helper);
15223
15224 {
15225 TestCompletionCallback callback;
15226
15227 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15228 EXPECT_EQ(ERR_IO_PENDING, rv);
15229
15230 rv = callback.WaitForResult();
15231 EXPECT_EQ(OK, rv);
15232 }
15233
15234 const HttpResponseInfo* response = trans->GetResponseInfo();
15235 ASSERT_TRUE(response);
15236 ASSERT_TRUE(response->headers.get());
15237 EXPECT_EQ(407, response->headers->response_code());
15238
15239 {
15240 TestCompletionCallback callback;
15241
15242 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
15243 callback.callback());
15244 EXPECT_EQ(ERR_IO_PENDING, rv);
15245
15246 rv = callback.WaitForResult();
15247 EXPECT_EQ(OK, rv);
15248 }
15249
15250 response = trans->GetResponseInfo();
15251 ASSERT_TRUE(response);
15252 ASSERT_TRUE(response->headers.get());
15253
15254 EXPECT_EQ(101, response->headers->response_code());
15255
15256 trans.reset();
15257 session->CloseAllConnections();
15258}
15259
15260// Verify that proxy headers are not sent to the destination server when
15261// establishing a tunnel for an insecure WebSocket connection.
15262// This requires the authentication info to be injected into the auth cache
15263// due to crbug.com/395064
15264// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
15265TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
15266 HttpRequestInfo request;
15267 request.method = "GET";
bncce36dca22015-04-21 22:11:2315268 request.url = GURL("ws://www.example.org/");
Adam Rice425cf122015-01-19 06:18:2415269 AddWebSocketHeaders(&request.extra_headers);
15270
15271 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:0315272 session_deps_.proxy_service =
15273 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
Adam Rice425cf122015-01-19 06:18:2415274
mmenkee65e7af2015-10-13 17:16:4215275 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2415276
15277 MockWrite data_writes[] = {
15278 // Try to establish a tunnel for the WebSocket connection, with
15279 // credentials. Because WebSockets have a separate set of socket pools,
15280 // they cannot and will not use the same TCP/IP connection as the
15281 // preflight HTTP request.
15282 MockWrite(
bncce36dca22015-04-21 22:11:2315283 "CONNECT www.example.org:80 HTTP/1.1\r\n"
15284 "Host: www.example.org:80\r\n"
Adam Rice425cf122015-01-19 06:18:2415285 "Proxy-Connection: keep-alive\r\n"
15286 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
15287
15288 MockWrite(
15289 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2315290 "Host: www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415291 "Connection: Upgrade\r\n"
15292 "Upgrade: websocket\r\n"
bncce36dca22015-04-21 22:11:2315293 "Origin: http://www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415294 "Sec-WebSocket-Version: 13\r\n"
15295 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
15296 };
15297
15298 MockRead data_reads[] = {
15299 // HTTP CONNECT with credentials.
15300 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15301
15302 // WebSocket connection established inside tunnel.
15303 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15304 MockRead("Upgrade: websocket\r\n"),
15305 MockRead("Connection: Upgrade\r\n"),
15306 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15307 };
15308
15309 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15310 arraysize(data_writes));
15311 session_deps_.socket_factory->AddSocketDataProvider(&data);
15312
15313 session->http_auth_cache()->Add(
15314 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
15315 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
15316
15317 scoped_ptr<HttpTransaction> trans(
15318 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15319 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15320 trans->SetWebSocketHandshakeStreamCreateHelper(
15321 &websocket_stream_create_helper);
15322
15323 TestCompletionCallback callback;
15324
15325 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15326 EXPECT_EQ(ERR_IO_PENDING, rv);
15327
15328 rv = callback.WaitForResult();
15329 EXPECT_EQ(OK, rv);
15330
15331 const HttpResponseInfo* response = trans->GetResponseInfo();
15332 ASSERT_TRUE(response);
15333 ASSERT_TRUE(response->headers.get());
15334
15335 EXPECT_EQ(101, response->headers->response_code());
15336
15337 trans.reset();
15338 session->CloseAllConnections();
15339}
15340
sclittlefb249892015-09-10 21:33:2215341TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
olli.raula6df48b2a2015-11-26 07:40:2215342 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15343 element_readers.push_back(
15344 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15345 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2215346
15347 HttpRequestInfo request;
15348 request.method = "POST";
15349 request.url = GURL("http://www.foo.com/");
15350 request.upload_data_stream = &upload_data_stream;
15351
mmenkee65e7af2015-10-13 17:16:4215352 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215353 scoped_ptr<HttpTransaction> trans(
15354 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15355 MockWrite data_writes[] = {
15356 MockWrite("POST / HTTP/1.1\r\n"
15357 "Host: www.foo.com\r\n"
15358 "Connection: keep-alive\r\n"
15359 "Content-Length: 3\r\n\r\n"),
15360 MockWrite("foo"),
15361 };
15362
15363 MockRead data_reads[] = {
15364 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15365 MockRead(SYNCHRONOUS, OK),
15366 };
15367 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15368 arraysize(data_writes));
15369 session_deps_.socket_factory->AddSocketDataProvider(&data);
15370
15371 TestCompletionCallback callback;
15372
15373 EXPECT_EQ(ERR_IO_PENDING,
15374 trans->Start(&request, callback.callback(), BoundNetLog()));
15375 EXPECT_EQ(OK, callback.WaitForResult());
15376
15377 std::string response_data;
15378 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15379
15380 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15381 trans->GetTotalSentBytes());
15382 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15383 trans->GetTotalReceivedBytes());
15384}
15385
15386TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
olli.raula6df48b2a2015-11-26 07:40:2215387 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15388 element_readers.push_back(
15389 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15390 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2215391
15392 HttpRequestInfo request;
15393 request.method = "POST";
15394 request.url = GURL("http://www.foo.com/");
15395 request.upload_data_stream = &upload_data_stream;
15396
mmenkee65e7af2015-10-13 17:16:4215397 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215398 scoped_ptr<HttpTransaction> trans(
15399 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15400 MockWrite data_writes[] = {
15401 MockWrite("POST / HTTP/1.1\r\n"
15402 "Host: www.foo.com\r\n"
15403 "Connection: keep-alive\r\n"
15404 "Content-Length: 3\r\n\r\n"),
15405 MockWrite("foo"),
15406 };
15407
15408 MockRead data_reads[] = {
15409 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
15410 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15411 MockRead(SYNCHRONOUS, OK),
15412 };
15413 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15414 arraysize(data_writes));
15415 session_deps_.socket_factory->AddSocketDataProvider(&data);
15416
15417 TestCompletionCallback callback;
15418
15419 EXPECT_EQ(ERR_IO_PENDING,
15420 trans->Start(&request, callback.callback(), BoundNetLog()));
15421 EXPECT_EQ(OK, callback.WaitForResult());
15422
15423 std::string response_data;
15424 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15425
15426 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15427 trans->GetTotalSentBytes());
15428 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15429 trans->GetTotalReceivedBytes());
15430}
15431
15432TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2215433 ChunkedUploadDataStream upload_data_stream(0);
15434
15435 HttpRequestInfo request;
15436 request.method = "POST";
15437 request.url = GURL("http://www.foo.com/");
15438 request.upload_data_stream = &upload_data_stream;
15439
mmenkee65e7af2015-10-13 17:16:4215440 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215441 scoped_ptr<HttpTransaction> trans(
15442 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15443 // Send headers successfully, but get an error while sending the body.
15444 MockWrite data_writes[] = {
15445 MockWrite("POST / HTTP/1.1\r\n"
15446 "Host: www.foo.com\r\n"
15447 "Connection: keep-alive\r\n"
15448 "Transfer-Encoding: chunked\r\n\r\n"),
15449 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
15450 };
15451
15452 MockRead data_reads[] = {
15453 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15454 MockRead(SYNCHRONOUS, OK),
15455 };
15456 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15457 arraysize(data_writes));
15458 session_deps_.socket_factory->AddSocketDataProvider(&data);
15459
15460 TestCompletionCallback callback;
15461
15462 EXPECT_EQ(ERR_IO_PENDING,
15463 trans->Start(&request, callback.callback(), BoundNetLog()));
15464
15465 base::RunLoop().RunUntilIdle();
15466 upload_data_stream.AppendData("f", 1, false);
15467
15468 base::RunLoop().RunUntilIdle();
15469 upload_data_stream.AppendData("oo", 2, true);
15470
15471 EXPECT_EQ(OK, callback.WaitForResult());
15472
15473 std::string response_data;
15474 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15475
15476 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15477 trans->GetTotalSentBytes());
15478 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15479 trans->GetTotalReceivedBytes());
15480}
15481
bncf4588402015-11-24 13:33:1815482TEST_P(HttpNetworkTransactionTest, EnableNPN) {
15483 session_deps_.next_protos = NextProtosDefaults();
15484 session_deps_.enable_npn = true;
15485
15486 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15487 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15488
15489 EXPECT_THAT(trans.server_ssl_config_.alpn_protos,
15490 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15491 EXPECT_THAT(trans.server_ssl_config_.npn_protos,
15492 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15493}
15494
15495TEST_P(HttpNetworkTransactionTest, DisableNPN) {
15496 session_deps_.next_protos = NextProtosDefaults();
15497 session_deps_.enable_npn = false;
15498
15499 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15500 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15501
15502 EXPECT_THAT(trans.server_ssl_config_.alpn_protos,
15503 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15504 EXPECT_TRUE(trans.server_ssl_config_.npn_protos.empty());
15505}
15506
[email protected]89ceba9a2009-03-21 03:46:0615507} // namespace net