blob: 670db0b6fb75d1616c62dbaf998223df07c24d84 [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"
bnc1b0e36852015-04-28 15:32:5923#include "base/stl_util.h"
[email protected]125ef482013-06-11 18:32:4724#include "base/strings/string_util.h"
[email protected]750b2f3c2013-06-07 18:41:0525#include "base/strings/utf_string_conversions.h"
[email protected]f36a8132011-09-02 18:36:3326#include "base/test/test_file_util.h"
skyostil4891b25b2015-06-11 11:43:4527#include "base/thread_task_runner_handle.h"
[email protected]277d5942010-08-11 21:02:3528#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0729#include "net/base/chunked_upload_data_stream.h"
[email protected]bacff652009-03-31 17:50:3330#include "net/base/completion_callback.h"
mmenkecbc2b712014-10-09 20:29:0731#include "net/base/elements_upload_data_stream.h"
[email protected]58e32bb2013-01-21 18:23:2532#include "net/base/load_timing_info.h"
33#include "net/base/load_timing_info_test_util.h"
Adam Rice425cf122015-01-19 06:18:2434#include "net/base/net_errors.h"
[email protected]ac790b42009-12-02 04:31:3135#include "net/base/request_priority.h"
initial.commit586acc5fe2008-07-26 22:42:5236#include "net/base/test_completion_callback.h"
[email protected]42fdb452012-11-01 12:44:4037#include "net/base/test_data_directory.h"
[email protected]b2d26cfd2012-12-11 10:36:0638#include "net/base/upload_bytes_element_reader.h"
[email protected]d98961652012-09-11 20:27:2139#include "net/base/upload_file_element_reader.h"
[email protected]6e7845ae2013-03-29 21:48:1140#include "net/cert/mock_cert_verifier.h"
[email protected]bc71b8772013-04-10 20:55:1641#include "net/dns/host_cache.h"
[email protected]f2cb3cf2013-03-21 01:40:5342#include "net/dns/mock_host_resolver.h"
[email protected]df41d0d82014-03-13 00:43:2443#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]3c32c5f2010-05-18 15:18:1244#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0045#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2946#include "net/http/http_auth_handler_ntlm.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"
[email protected]6e7845ae2013-03-29 21:48:1181#include "net/test/cert_test_util.h"
[email protected]831e4a32013-11-14 02:14:4482#include "net/websockets/websocket_handshake_stream_base.h"
initial.commit586acc5fe2008-07-26 22:42:5283#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1584#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:2785#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:5286
[email protected]ad65a3e2013-12-25 18:18:0187using base::ASCIIToUTF16;
88
initial.commit586acc5fe2008-07-26 22:42:5289//-----------------------------------------------------------------------------
90
ttuttle859dc7a2015-04-23 19:42:2991namespace net {
92
[email protected]13c8a092010-07-29 06:15:4493namespace {
94
[email protected]42cba2fb2013-03-29 19:58:5795const base::string16 kBar(ASCIIToUTF16("bar"));
96const base::string16 kBar2(ASCIIToUTF16("bar2"));
97const base::string16 kBar3(ASCIIToUTF16("bar3"));
98const base::string16 kBaz(ASCIIToUTF16("baz"));
99const base::string16 kFirst(ASCIIToUTF16("first"));
100const base::string16 kFoo(ASCIIToUTF16("foo"));
101const base::string16 kFoo2(ASCIIToUTF16("foo2"));
102const base::string16 kFoo3(ASCIIToUTF16("foo3"));
103const base::string16 kFou(ASCIIToUTF16("fou"));
104const base::string16 kSecond(ASCIIToUTF16("second"));
105const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
106const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44107
ttuttle859dc7a2015-04-23 19:42:29108int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
109 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
110 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02111}
112
ttuttle859dc7a2015-04-23 19:42:29113int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession* session) {
114 return session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
115 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02116}
117
ttuttle859dc7a2015-04-23 19:42:29118bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
119 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
120 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52121}
122
[email protected]f3da152d2012-06-02 01:00:57123// Takes in a Value created from a NetLogHttpResponseParameter, and returns
124// a JSONified list of headers as a single string. Uses single quotes instead
125// of double quotes for easier comparison. Returns false on failure.
[email protected]ea5ef4c2013-06-13 22:50:27126bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
[email protected]f3da152d2012-06-02 01:00:57127 if (!params)
128 return false;
[email protected]ea5ef4c2013-06-13 22:50:27129 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:57130 if (!params->GetList("headers", &header_list))
131 return false;
132 std::string double_quote_headers;
estade8d046462015-05-16 01:02:34133 base::JSONWriter::Write(*header_list, &double_quote_headers);
[email protected]466c9862013-12-03 22:05:28134 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
[email protected]f3da152d2012-06-02 01:00:57135 return true;
136}
137
[email protected]029c83b62013-01-24 05:28:20138// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
139// used.
ttuttle859dc7a2015-04-23 19:42:29140void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20141 EXPECT_TRUE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29142 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25143
[email protected]029c83b62013-01-24 05:28:20144 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
145 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
146
ttuttle859dc7a2015-04-23 19:42:29147 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20148 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25149
150 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25151
[email protected]3b23a222013-05-15 21:33:25152 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25153 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
154 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25155 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25156}
157
[email protected]029c83b62013-01-24 05:28:20158// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
159// used.
ttuttle859dc7a2015-04-23 19:42:29160void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25161 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20162 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29163 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20164
165 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
166 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
167
ttuttle859dc7a2015-04-23 19:42:29168 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
169 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20170 EXPECT_LE(load_timing_info.connect_timing.connect_end,
171 load_timing_info.send_start);
172
173 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20174
[email protected]3b23a222013-05-15 21:33:25175 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20176 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
177 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25178 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20179}
180
181// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
182// used.
ttuttle859dc7a2015-04-23 19:42:29183void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20184 EXPECT_TRUE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29185 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20186
ttuttle859dc7a2015-04-23 19:42:29187 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20188
189 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
190 EXPECT_LE(load_timing_info.proxy_resolve_start,
191 load_timing_info.proxy_resolve_end);
192 EXPECT_LE(load_timing_info.proxy_resolve_end,
193 load_timing_info.send_start);
194 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20195
[email protected]3b23a222013-05-15 21:33:25196 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20197 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
198 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25199 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20200}
201
202// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
203// used.
ttuttle859dc7a2015-04-23 19:42:29204void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20205 int connect_timing_flags) {
206 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29207 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20208
209 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
210 EXPECT_LE(load_timing_info.proxy_resolve_start,
211 load_timing_info.proxy_resolve_end);
212 EXPECT_LE(load_timing_info.proxy_resolve_end,
213 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29214 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
215 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20216 EXPECT_LE(load_timing_info.connect_timing.connect_end,
217 load_timing_info.send_start);
218
219 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20220
[email protected]3b23a222013-05-15 21:33:25221 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20222 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
223 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25224 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25225}
226
ttuttle859dc7a2015-04-23 19:42:29227void AddWebSocketHeaders(HttpRequestHeaders* headers) {
Adam Rice425cf122015-01-19 06:18:24228 headers->SetHeader("Connection", "Upgrade");
229 headers->SetHeader("Upgrade", "websocket");
bncce36dca22015-04-21 22:11:23230 headers->SetHeader("Origin", "http://www.example.org");
Adam Rice425cf122015-01-19 06:18:24231 headers->SetHeader("Sec-WebSocket-Version", "13");
232 headers->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
233}
234
mmenke6b3af6e2015-09-12 02:06:06235HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34236 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14237}
238
[email protected]448d4ca52012-03-04 04:12:23239} // namespace
240
[email protected]23e482282013-06-14 16:08:02241class HttpNetworkTransactionTest
242 : public PlatformTest,
243 public ::testing::WithParamInterface<NextProto> {
[email protected]483fa202013-05-14 01:07:03244 public:
[email protected]23e482282013-06-14 16:08:02245 virtual ~HttpNetworkTransactionTest() {
[email protected]483fa202013-05-14 01:07:03246 // Important to restore the per-pool limit first, since the pool limit must
247 // always be greater than group limit, and the tests reduce both limits.
248 ClientSocketPoolManager::set_max_sockets_per_pool(
249 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
250 ClientSocketPoolManager::set_max_sockets_per_group(
251 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
252 }
253
[email protected]e3ceb682011-06-28 23:55:46254 protected:
[email protected]23e482282013-06-14 16:08:02255 HttpNetworkTransactionTest()
256 : spdy_util_(GetParam()),
257 session_deps_(GetParam()),
[email protected]483fa202013-05-14 01:07:03258 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
259 HttpNetworkSession::NORMAL_SOCKET_POOL)),
260 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
261 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
262 }
[email protected]bb88e1d32013-05-03 23:11:07263
[email protected]e3ceb682011-06-28 23:55:46264 struct SimpleGetHelperResult {
265 int rv;
266 std::string status_line;
267 std::string response_data;
sclittlefb249892015-09-10 21:33:22268 int64_t total_received_bytes;
269 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25270 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47271 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59272 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46273 };
274
dcheng67be2b1f2014-10-27 21:47:29275 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50276 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34277 base::MessageLoop::current()->RunUntilIdle();
[email protected]2ff8b312010-04-26 22:20:54278 }
279
dcheng67be2b1f2014-10-27 21:47:29280 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50281 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34282 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09283 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:34284 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09285 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50286 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34287 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09288 }
289
bnc33b8cef42014-11-19 17:30:38290 const char* GetAlternateProtocolFromParam() {
291 return
292 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam()));
293 }
294
bncc958faa2015-07-31 18:14:52295 std::string GetAlternativeServiceHttpHeader() {
296 return std::string("Alt-Svc: ") + GetAlternateProtocolFromParam() +
297 "=\"www.example.com:443\"\r\n";
298 }
299
[email protected]8a0fc822013-06-27 20:52:43300 std::string GetAlternateProtocolHttpHeader() {
bnc33b8cef42014-11-19 17:30:38301 return std::string("Alternate-Protocol: 443:") +
bncc958faa2015-07-31 18:14:52302 GetAlternateProtocolFromParam() + "\r\n";
[email protected]8a0fc822013-06-27 20:52:43303 }
304
[email protected]202965992011-12-07 23:04:51305 // Either |write_failure| specifies a write failure or |read_failure|
306 // specifies a read failure when using a reused socket. In either case, the
307 // failure should cause the network transaction to resend the request, and the
308 // other argument should be NULL.
309 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
310 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52311
[email protected]a34f61ee2014-03-18 20:59:49312 // Either |write_failure| specifies a write failure or |read_failure|
313 // specifies a read failure when using a reused socket. In either case, the
314 // failure should cause the network transaction to resend the request, and the
315 // other argument should be NULL.
316 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10317 const MockRead* read_failure,
318 bool use_spdy);
[email protected]a34f61ee2014-03-18 20:59:49319
[email protected]5a60c8b2011-10-19 20:14:29320 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
321 size_t data_count) {
[email protected]ff007e162009-05-23 09:13:15322 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52323
[email protected]ff007e162009-05-23 09:13:15324 HttpRequestInfo request;
325 request.method = "GET";
bncce36dca22015-04-21 22:11:23326 request.url = GURL("http://www.example.org/");
[email protected]ff007e162009-05-23 09:13:15327 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52328
vishal.b62985ca92015-04-17 08:45:51329 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07330 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:06331 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:27332 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:41333 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:27334
[email protected]5a60c8b2011-10-19 20:14:29335 for (size_t i = 0; i < data_count; ++i) {
[email protected]bb88e1d32013-05-03 23:11:07336 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
[email protected]5a60c8b2011-10-19 20:14:29337 }
initial.commit586acc5fe2008-07-26 22:42:52338
[email protected]49639fa2011-12-20 23:22:41339 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52340
eroman24bc6a12015-05-06 19:55:48341 EXPECT_TRUE(log.bound().IsCapturing());
[email protected]49639fa2011-12-20 23:22:41342 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]ff007e162009-05-23 09:13:15343 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52344
[email protected]ff007e162009-05-23 09:13:15345 out.rv = callback.WaitForResult();
sclittlefb249892015-09-10 21:33:22346 out.total_received_bytes = trans->GetTotalReceivedBytes();
347 out.total_sent_bytes = trans->GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25348
349 // Even in the failure cases that use this function, connections are always
350 // successfully established before the error.
351 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
352 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
353
[email protected]ff007e162009-05-23 09:13:15354 if (out.rv != OK)
355 return out;
356
357 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50358 // Can't use ASSERT_* inside helper functions like this, so
359 // return an error.
[email protected]90499482013-06-01 00:39:50360 if (response == NULL || response->headers.get() == NULL) {
[email protected]fe2255a2011-09-20 19:37:50361 out.rv = ERR_UNEXPECTED;
362 return out;
363 }
[email protected]ff007e162009-05-23 09:13:15364 out.status_line = response->headers->GetStatusLine();
365
[email protected]80a09a82012-11-16 17:40:06366 EXPECT_EQ("127.0.0.1", response->socket_address.host());
367 EXPECT_EQ(80, response->socket_address.port());
[email protected]6d81b482011-02-22 19:47:19368
ttuttled9dbc652015-09-29 20:00:59369 bool got_endpoint =
370 trans->GetRemoteEndpoint(&out.remote_endpoint_after_start);
371 EXPECT_EQ(got_endpoint,
372 out.remote_endpoint_after_start.address().size() > 0);
373
[email protected]ff007e162009-05-23 09:13:15374 rv = ReadTransaction(trans.get(), &out.response_data);
375 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40376
mmenke43758e62015-05-04 21:09:46377 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:40378 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39379 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40380 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12381 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39382 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40383 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39384 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
385 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15386
[email protected]f3da152d2012-06-02 01:00:57387 std::string line;
388 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
389 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
390
[email protected]79e1fd62013-06-20 06:50:04391 HttpRequestHeaders request_headers;
392 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
393 std::string value;
394 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
bncce36dca22015-04-21 22:11:23395 EXPECT_EQ("www.example.org", value);
[email protected]79e1fd62013-06-20 06:50:04396 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
397 EXPECT_EQ("keep-alive", value);
398
399 std::string response_headers;
400 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
bncce36dca22015-04-21 22:11:23401 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
[email protected]79e1fd62013-06-20 06:50:04402 response_headers);
[email protected]3deb9a52010-11-11 00:24:40403
sclittlefb249892015-09-10 21:33:22404 out.total_received_bytes = trans->GetTotalReceivedBytes();
405 // The total number of sent bytes should not have changed.
406 EXPECT_EQ(out.total_sent_bytes, trans->GetTotalSentBytes());
407
ttuttle1f2d7e92015-04-28 16:17:47408 trans->GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47409 return out;
[email protected]ff007e162009-05-23 09:13:15410 }
initial.commit586acc5fe2008-07-26 22:42:52411
[email protected]5a60c8b2011-10-19 20:14:29412 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
413 size_t reads_count) {
sclittlefb249892015-09-10 21:33:22414 MockWrite data_writes[] = {
415 MockWrite("GET / HTTP/1.1\r\n"
416 "Host: www.example.org\r\n"
417 "Connection: keep-alive\r\n\r\n"),
418 };
[email protected]5a60c8b2011-10-19 20:14:29419
sclittlefb249892015-09-10 21:33:22420 StaticSocketDataProvider reads(data_reads, reads_count, data_writes,
421 arraysize(data_writes));
422 StaticSocketDataProvider* data[] = {&reads};
423 SimpleGetHelperResult out = SimpleGetHelperForData(data, 1);
424
425 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
426 out.total_sent_bytes);
427 return out;
[email protected]b8015c42013-12-24 15:18:19428 }
429
[email protected]ff007e162009-05-23 09:13:15430 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
431 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52432
[email protected]ff007e162009-05-23 09:13:15433 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07434
435 void BypassHostCacheOnRefreshHelper(int load_flags);
436
437 void CheckErrorIsPassedBack(int error, IoMode mode);
438
[email protected]4bd46222013-05-14 19:32:23439 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07440 SpdySessionDependencies session_deps_;
[email protected]483fa202013-05-14 01:07:03441
442 // Original socket limits. Some tests set these. Safest to always restore
443 // them once each test has been run.
444 int old_max_group_sockets_;
445 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15446};
[email protected]231d5a32008-09-13 00:45:27447
bnc57685ae62015-03-10 21:27:20448INSTANTIATE_TEST_CASE_P(NextProto,
449 HttpNetworkTransactionTest,
450 testing::Values(kProtoSPDY31,
bnc06d22432015-06-29 12:39:43451 kProtoHTTP2));
[email protected]23e482282013-06-14 16:08:02452
[email protected]448d4ca52012-03-04 04:12:23453namespace {
454
[email protected]1826a402014-01-08 15:40:48455class BeforeNetworkStartHandler {
456 public:
457 explicit BeforeNetworkStartHandler(bool defer)
458 : defer_on_before_network_start_(defer),
459 observed_before_network_start_(false) {}
460
461 void OnBeforeNetworkStart(bool* defer) {
462 *defer = defer_on_before_network_start_;
463 observed_before_network_start_ = true;
464 }
465
466 bool observed_before_network_start() const {
467 return observed_before_network_start_;
468 }
469
470 private:
471 const bool defer_on_before_network_start_;
472 bool observed_before_network_start_;
473
474 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
475};
476
[email protected]597a1ab2014-06-26 08:12:27477class BeforeProxyHeadersSentHandler {
478 public:
479 BeforeProxyHeadersSentHandler()
480 : observed_before_proxy_headers_sent_(false) {}
481
[email protected]1252d42f2014-07-01 21:20:20482 void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
483 HttpRequestHeaders* request_headers) {
[email protected]597a1ab2014-06-26 08:12:27484 observed_before_proxy_headers_sent_ = true;
485 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
486 }
487
488 bool observed_before_proxy_headers_sent() const {
489 return observed_before_proxy_headers_sent_;
490 }
491
492 std::string observed_proxy_server_uri() const {
493 return observed_proxy_server_uri_;
494 }
495
496 private:
497 bool observed_before_proxy_headers_sent_;
498 std::string observed_proxy_server_uri_;
499
500 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler);
501};
502
[email protected]15a5ccf82008-10-23 19:57:43503// Fill |str| with a long header list that consumes >= |size| bytes.
504void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51505 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19506 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
507 const int sizeof_row = strlen(row);
508 const int num_rows = static_cast<int>(
509 ceil(static_cast<float>(size) / sizeof_row));
510 const int sizeof_data = num_rows * sizeof_row;
511 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43512 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51513
[email protected]4ddaf2502008-10-23 18:26:19514 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43515 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19516}
517
thakis84dff942015-07-28 20:47:38518#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29519// Alternative functions that eliminate randomness and dependency on the local
520// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20521void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29522 static const uint8 bytes[] = {
523 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
524 };
525 static size_t current_byte = 0;
526 for (size_t i = 0; i < n; ++i) {
527 output[i] = bytes[current_byte++];
528 current_byte %= arraysize(bytes);
529 }
530}
531
[email protected]fe2bc6a2009-03-23 16:52:20532void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29533 static const uint8 bytes[] = {
534 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
535 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
536 };
537 static size_t current_byte = 0;
538 for (size_t i = 0; i < n; ++i) {
539 output[i] = bytes[current_byte++];
540 current_byte %= arraysize(bytes);
541 }
542}
543
[email protected]fe2bc6a2009-03-23 16:52:20544std::string MockGetHostName() {
545 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29546}
thakis84dff942015-07-28 20:47:38547#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29548
[email protected]e60e47a2010-07-14 03:37:18549template<typename ParentPool>
550class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31551 public:
[email protected]9e1bdd32011-02-03 21:48:34552 CaptureGroupNameSocketPool(HostResolver* host_resolver,
553 CertVerifier* cert_verifier);
[email protected]e60e47a2010-07-14 03:37:18554
[email protected]d80a4322009-08-14 07:07:49555 const std::string last_group_name_received() const {
556 return last_group_name_;
557 }
558
dmichaeld6e570d2014-12-18 22:30:57559 int RequestSocket(const std::string& group_name,
560 const void* socket_params,
561 RequestPriority priority,
562 ClientSocketHandle* handle,
563 const CompletionCallback& callback,
564 const BoundNetLog& net_log) override {
[email protected]04e5be32009-06-26 20:00:31565 last_group_name_ = group_name;
566 return ERR_IO_PENDING;
567 }
dmichaeld6e570d2014-12-18 22:30:57568 void CancelRequest(const std::string& group_name,
569 ClientSocketHandle* handle) override {}
570 void ReleaseSocket(const std::string& group_name,
571 scoped_ptr<StreamSocket> socket,
572 int id) override {}
573 void CloseIdleSockets() override {}
574 int IdleSocketCount() const override { return 0; }
575 int IdleSocketCountInGroup(const std::string& group_name) const override {
[email protected]04e5be32009-06-26 20:00:31576 return 0;
577 }
dmichaeld6e570d2014-12-18 22:30:57578 LoadState GetLoadState(const std::string& group_name,
579 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31580 return LOAD_STATE_IDLE;
581 }
dmichaeld6e570d2014-12-18 22:30:57582 base::TimeDelta ConnectionTimeout() const override {
[email protected]a796bcec2010-03-22 17:17:26583 return base::TimeDelta();
584 }
[email protected]d80a4322009-08-14 07:07:49585
586 private:
[email protected]04e5be32009-06-26 20:00:31587 std::string last_group_name_;
588};
589
[email protected]ab739042011-04-07 15:22:28590typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
591CaptureGroupNameTransportSocketPool;
[email protected]e772db3f2010-07-12 18:11:13592typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
593CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06594typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11595CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18596typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
597CaptureGroupNameSSLSocketPool;
598
rkaplowd90695c2015-03-25 22:12:41599template <typename ParentPool>
[email protected]e60e47a2010-07-14 03:37:18600CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34601 HostResolver* host_resolver,
602 CertVerifier* /* cert_verifier */)
rkaplowd90695c2015-03-25 22:12:41603 : ParentPool(0, 0, host_resolver, NULL, NULL) {
604}
[email protected]e60e47a2010-07-14 03:37:18605
hashimoto0d3e4fb2015-01-09 05:02:50606template <>
[email protected]2df19bb2010-08-25 20:13:46607CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
hashimotodae13b02015-01-15 04:28:21608 HostResolver* /* host_resolver */,
[email protected]9e1bdd32011-02-03 21:48:34609 CertVerifier* /* cert_verifier */)
rkaplowd90695c2015-03-25 22:12:41610 : HttpProxyClientSocketPool(0, 0, NULL, NULL, NULL) {
hashimoto0d3e4fb2015-01-09 05:02:50611}
[email protected]2df19bb2010-08-25 20:13:46612
[email protected]007b3f82013-04-09 08:46:45613template <>
[email protected]e60e47a2010-07-14 03:37:18614CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
hashimotodae13b02015-01-15 04:28:21615 HostResolver* /* host_resolver */,
[email protected]9e1bdd32011-02-03 21:48:34616 CertVerifier* cert_verifier)
[email protected]007b3f82013-04-09 08:46:45617 : SSLClientSocketPool(0,
618 0,
[email protected]007b3f82013-04-09 08:46:45619 cert_verifier,
620 NULL,
621 NULL,
[email protected]284303b62013-11-28 15:11:54622 NULL,
eranm6571b2b2014-12-03 15:53:23623 NULL,
[email protected]007b3f82013-04-09 08:46:45624 std::string(),
625 NULL,
626 NULL,
627 NULL,
628 NULL,
629 NULL,
[email protected]8e458552014-08-05 00:02:15630 NULL) {
631}
[email protected]2227c692010-05-04 15:36:11632
[email protected]231d5a32008-09-13 00:45:27633//-----------------------------------------------------------------------------
634
[email protected]79cb5c12011-09-12 13:12:04635// Helper functions for validating that AuthChallengeInfo's are correctly
636// configured for common cases.
637bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
638 if (!auth_challenge)
639 return false;
640 EXPECT_FALSE(auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:23641 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:04642 EXPECT_EQ("MyRealm1", auth_challenge->realm);
643 EXPECT_EQ("basic", auth_challenge->scheme);
644 return true;
645}
646
647bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
648 if (!auth_challenge)
649 return false;
650 EXPECT_TRUE(auth_challenge->is_proxy);
651 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
652 EXPECT_EQ("MyRealm1", auth_challenge->realm);
653 EXPECT_EQ("basic", auth_challenge->scheme);
654 return true;
655}
656
657bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
658 if (!auth_challenge)
659 return false;
660 EXPECT_FALSE(auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:23661 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:04662 EXPECT_EQ("digestive", auth_challenge->realm);
663 EXPECT_EQ("digest", auth_challenge->scheme);
664 return true;
665}
666
thakis84dff942015-07-28 20:47:38667#if defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04668bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
669 if (!auth_challenge)
670 return false;
671 EXPECT_FALSE(auth_challenge->is_proxy);
672 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
673 EXPECT_EQ(std::string(), auth_challenge->realm);
674 EXPECT_EQ("ntlm", auth_challenge->scheme);
675 return true;
676}
thakis84dff942015-07-28 20:47:38677#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04678
[email protected]448d4ca52012-03-04 04:12:23679} // namespace
680
[email protected]23e482282013-06-14 16:08:02681TEST_P(HttpNetworkTransactionTest, Basic) {
mmenke6b3af6e2015-09-12 02:06:06682 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:40683 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:41684 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]231d5a32008-09-13 00:45:27685}
686
[email protected]23e482282013-06-14 16:08:02687TEST_P(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27688 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35689 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
690 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06691 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27692 };
[email protected]31a2bfe2010-02-09 08:03:39693 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
694 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42695 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27696 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
697 EXPECT_EQ("hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22698 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
699 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47700 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59701
702 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27703}
704
705// Response with no status line.
[email protected]23e482282013-06-14 16:08:02706TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27707 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35708 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06709 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27710 };
[email protected]31a2bfe2010-02-09 08:03:39711 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
712 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42713 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27714 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
715 EXPECT_EQ("hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22716 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
717 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27718}
719
720// Allow up to 4 bytes of junk to precede status line.
[email protected]23e482282013-06-14 16:08:02721TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27722 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35723 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06724 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27725 };
[email protected]31a2bfe2010-02-09 08:03:39726 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
727 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42728 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27729 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
730 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22731 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
732 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27733}
734
735// Allow up to 4 bytes of junk to precede status line.
[email protected]23e482282013-06-14 16:08:02736TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27737 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35738 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06739 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27740 };
[email protected]31a2bfe2010-02-09 08:03:39741 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
742 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42743 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27744 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
745 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22746 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
747 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27748}
749
750// Beyond 4 bytes of slop and it should fail to find a status line.
[email protected]23e482282013-06-14 16:08:02751TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27752 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35753 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06754 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27755 };
[email protected]31a2bfe2010-02-09 08:03:39756 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
757 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42758 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25759 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
760 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
sclittlefb249892015-09-10 21:33:22761 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
762 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27763}
764
765// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
[email protected]23e482282013-06-14 16:08:02766TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27767 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35768 MockRead("\n"),
769 MockRead("\n"),
770 MockRead("Q"),
771 MockRead("J"),
772 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06773 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27774 };
[email protected]31a2bfe2010-02-09 08:03:39775 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
776 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42777 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27778 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
779 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22780 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
781 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27782}
783
784// Close the connection before enough bytes to have a status line.
[email protected]23e482282013-06-14 16:08:02785TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27786 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35787 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06788 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27789 };
[email protected]31a2bfe2010-02-09 08:03:39790 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
791 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42792 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27793 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
794 EXPECT_EQ("HTT", out.response_data);
sclittlefb249892015-09-10 21:33:22795 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
796 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:52797}
798
[email protected]f9d44aa2008-09-23 23:57:17799// Simulate a 204 response, lacking a Content-Length header, sent over a
800// persistent connection. The response should still terminate since a 204
801// cannot have a response body.
[email protected]23e482282013-06-14 16:08:02802TEST_P(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:19803 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:17804 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35805 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:19806 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:06807 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:17808 };
[email protected]31a2bfe2010-02-09 08:03:39809 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
810 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42811 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17812 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
813 EXPECT_EQ("", out.response_data);
sclittlefb249892015-09-10 21:33:22814 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
815 int64_t response_size = reads_size - strlen(junk);
816 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:17817}
818
[email protected]0877e3d2009-10-17 22:29:57819// A simple request using chunked encoding with some extra data after.
[email protected]23e482282013-06-14 16:08:02820TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:19821 std::string final_chunk = "0\r\n\r\n";
822 std::string extra_data = "HTTP/1.1 200 OK\r\n";
823 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:57824 MockRead data_reads[] = {
825 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
826 MockRead("5\r\nHello\r\n"),
827 MockRead("1\r\n"),
828 MockRead(" \r\n"),
829 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:19830 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:06831 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:57832 };
[email protected]31a2bfe2010-02-09 08:03:39833 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
834 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57835 EXPECT_EQ(OK, out.rv);
836 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
837 EXPECT_EQ("Hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22838 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
839 int64_t response_size = reads_size - extra_data.size();
840 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:57841}
842
[email protected]9fe44f52010-09-23 18:36:00843// Next tests deal with http://crbug.com/56344.
844
[email protected]23e482282013-06-14 16:08:02845TEST_P(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00846 MultipleContentLengthHeadersNoTransferEncoding) {
847 MockRead data_reads[] = {
848 MockRead("HTTP/1.1 200 OK\r\n"),
849 MockRead("Content-Length: 10\r\n"),
850 MockRead("Content-Length: 5\r\n\r\n"),
851 };
852 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
853 arraysize(data_reads));
854 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
855}
856
[email protected]23e482282013-06-14 16:08:02857TEST_P(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04858 DuplicateContentLengthHeadersNoTransferEncoding) {
859 MockRead data_reads[] = {
860 MockRead("HTTP/1.1 200 OK\r\n"),
861 MockRead("Content-Length: 5\r\n"),
862 MockRead("Content-Length: 5\r\n\r\n"),
863 MockRead("Hello"),
864 };
865 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
866 arraysize(data_reads));
867 EXPECT_EQ(OK, out.rv);
868 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
869 EXPECT_EQ("Hello", out.response_data);
870}
871
[email protected]23e482282013-06-14 16:08:02872TEST_P(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04873 ComplexContentLengthHeadersNoTransferEncoding) {
874 // More than 2 dupes.
875 {
876 MockRead data_reads[] = {
877 MockRead("HTTP/1.1 200 OK\r\n"),
878 MockRead("Content-Length: 5\r\n"),
879 MockRead("Content-Length: 5\r\n"),
880 MockRead("Content-Length: 5\r\n\r\n"),
881 MockRead("Hello"),
882 };
883 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
884 arraysize(data_reads));
885 EXPECT_EQ(OK, out.rv);
886 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
887 EXPECT_EQ("Hello", out.response_data);
888 }
889 // HTTP/1.0
890 {
891 MockRead data_reads[] = {
892 MockRead("HTTP/1.0 200 OK\r\n"),
893 MockRead("Content-Length: 5\r\n"),
894 MockRead("Content-Length: 5\r\n"),
895 MockRead("Content-Length: 5\r\n\r\n"),
896 MockRead("Hello"),
897 };
898 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
899 arraysize(data_reads));
900 EXPECT_EQ(OK, out.rv);
901 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
902 EXPECT_EQ("Hello", out.response_data);
903 }
904 // 2 dupes and one mismatched.
905 {
906 MockRead data_reads[] = {
907 MockRead("HTTP/1.1 200 OK\r\n"),
908 MockRead("Content-Length: 10\r\n"),
909 MockRead("Content-Length: 10\r\n"),
910 MockRead("Content-Length: 5\r\n\r\n"),
911 };
912 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
913 arraysize(data_reads));
914 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
915 }
916}
917
[email protected]23e482282013-06-14 16:08:02918TEST_P(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00919 MultipleContentLengthHeadersTransferEncoding) {
920 MockRead data_reads[] = {
921 MockRead("HTTP/1.1 200 OK\r\n"),
922 MockRead("Content-Length: 666\r\n"),
923 MockRead("Content-Length: 1337\r\n"),
924 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
925 MockRead("5\r\nHello\r\n"),
926 MockRead("1\r\n"),
927 MockRead(" \r\n"),
928 MockRead("5\r\nworld\r\n"),
929 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:06930 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:00931 };
932 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
933 arraysize(data_reads));
934 EXPECT_EQ(OK, out.rv);
935 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
936 EXPECT_EQ("Hello world", out.response_data);
937}
938
[email protected]1628fe92011-10-04 23:04:55939// Next tests deal with http://crbug.com/98895.
940
941// Checks that a single Content-Disposition header results in no error.
[email protected]23e482282013-06-14 16:08:02942TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:55943 MockRead data_reads[] = {
944 MockRead("HTTP/1.1 200 OK\r\n"),
945 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
946 MockRead("Content-Length: 5\r\n\r\n"),
947 MockRead("Hello"),
948 };
949 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
950 arraysize(data_reads));
951 EXPECT_EQ(OK, out.rv);
952 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
953 EXPECT_EQ("Hello", out.response_data);
954}
955
[email protected]54a9c6e52012-03-21 20:10:59956// Checks that two identical Content-Disposition headers result in no error.
[email protected]23e482282013-06-14 16:08:02957TEST_P(HttpNetworkTransactionTest,
[email protected]54a9c6e52012-03-21 20:10:59958 TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:55959 MockRead data_reads[] = {
960 MockRead("HTTP/1.1 200 OK\r\n"),
961 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
962 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
963 MockRead("Content-Length: 5\r\n\r\n"),
964 MockRead("Hello"),
965 };
966 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
967 arraysize(data_reads));
[email protected]54a9c6e52012-03-21 20:10:59968 EXPECT_EQ(OK, out.rv);
969 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
970 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:55971}
972
973// Checks that two distinct Content-Disposition headers result in an error.
[email protected]23e482282013-06-14 16:08:02974TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:55975 MockRead data_reads[] = {
976 MockRead("HTTP/1.1 200 OK\r\n"),
977 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
978 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
979 MockRead("Content-Length: 5\r\n\r\n"),
980 MockRead("Hello"),
981 };
982 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
983 arraysize(data_reads));
984 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
985}
986
[email protected]54a9c6e52012-03-21 20:10:59987// Checks that two identical Location headers result in no error.
988// Also tests Location header behavior.
[email protected]23e482282013-06-14 16:08:02989TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:55990 MockRead data_reads[] = {
991 MockRead("HTTP/1.1 302 Redirect\r\n"),
992 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:59993 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:55994 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:06995 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:55996 };
997
998 HttpRequestInfo request;
999 request.method = "GET";
1000 request.url = GURL("http://redirect.com/");
1001 request.load_flags = 0;
1002
mmenke6b3af6e2015-09-12 02:06:061003 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1628fe92011-10-04 23:04:551004 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411005 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]1628fe92011-10-04 23:04:551006
1007 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071008 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551009
[email protected]49639fa2011-12-20 23:22:411010 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551011
[email protected]49639fa2011-12-20 23:22:411012 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1628fe92011-10-04 23:04:551013 EXPECT_EQ(ERR_IO_PENDING, rv);
1014
1015 EXPECT_EQ(OK, callback.WaitForResult());
1016
1017 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501018 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
[email protected]1628fe92011-10-04 23:04:551019 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1020 std::string url;
1021 EXPECT_TRUE(response->headers->IsRedirect(&url));
1022 EXPECT_EQ("http://good.com/", url);
[email protected]d8fc4722014-06-13 13:17:151023 EXPECT_TRUE(response->proxy_server.IsEmpty());
[email protected]1628fe92011-10-04 23:04:551024}
1025
[email protected]1628fe92011-10-04 23:04:551026// Checks that two distinct Location headers result in an error.
[email protected]23e482282013-06-14 16:08:021027TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551028 MockRead data_reads[] = {
1029 MockRead("HTTP/1.1 302 Redirect\r\n"),
1030 MockRead("Location: http://good.com/\r\n"),
1031 MockRead("Location: http://evil.com/\r\n"),
1032 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061033 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551034 };
1035 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1036 arraysize(data_reads));
1037 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
1038}
1039
[email protected]ef0faf2e72009-03-05 23:27:231040// Do a request using the HEAD method. Verify that we don't try to read the
1041// message body (since HEAD has none).
[email protected]23e482282013-06-14 16:08:021042TEST_P(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421043 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231044 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231045 request.url = GURL("http://www.example.org/");
[email protected]ef0faf2e72009-03-05 23:27:231046 request.load_flags = 0;
1047
mmenke6b3af6e2015-09-12 02:06:061048 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271049 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411050 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]597a1ab2014-06-26 08:12:271051 BeforeProxyHeadersSentHandler proxy_headers_handler;
1052 trans->SetBeforeProxyHeadersSentCallback(
1053 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
1054 base::Unretained(&proxy_headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271055
[email protected]ef0faf2e72009-03-05 23:27:231056 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131057 MockWrite("HEAD / HTTP/1.1\r\n"
1058 "Host: www.example.org\r\n"
1059 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231060 };
1061 MockRead data_reads1[] = {
1062 MockRead("HTTP/1.1 404 Not Found\r\n"),
1063 MockRead("Server: Blah\r\n"),
1064 MockRead("Content-Length: 1234\r\n\r\n"),
1065
1066 // No response body because the test stops reading here.
[email protected]8ddf8322012-02-23 18:08:061067 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:231068 };
1069
[email protected]31a2bfe2010-02-09 08:03:391070 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1071 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:071072 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231073
[email protected]49639fa2011-12-20 23:22:411074 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231075
[email protected]49639fa2011-12-20 23:22:411076 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421077 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:231078
1079 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421080 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:231081
[email protected]1c773ea12009-04-28 19:58:421082 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501083 ASSERT_TRUE(response != NULL);
[email protected]ef0faf2e72009-03-05 23:27:231084
1085 // Check that the headers got parsed.
[email protected]90499482013-06-01 00:39:501086 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]ef0faf2e72009-03-05 23:27:231087 EXPECT_EQ(1234, response->headers->GetContentLength());
1088 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151089 EXPECT_TRUE(response->proxy_server.IsEmpty());
[email protected]597a1ab2014-06-26 08:12:271090 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
[email protected]ef0faf2e72009-03-05 23:27:231091
1092 std::string server_header;
1093 void* iter = NULL;
1094 bool has_server_header = response->headers->EnumerateHeader(
1095 &iter, "Server", &server_header);
1096 EXPECT_TRUE(has_server_header);
1097 EXPECT_EQ("Blah", server_header);
1098
1099 // Reading should give EOF right away, since there is no message body
1100 // (despite non-zero content-length).
1101 std::string response_data;
1102 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421103 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:231104 EXPECT_EQ("", response_data);
1105}
1106
[email protected]23e482282013-06-14 16:08:021107TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
mmenke6b3af6e2015-09-12 02:06:061108 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521109
1110 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351111 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1112 MockRead("hello"),
1113 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1114 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061115 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521116 };
[email protected]31a2bfe2010-02-09 08:03:391117 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071118 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521119
[email protected]0b0bf032010-09-21 18:08:501120 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521121 "hello", "world"
1122 };
1123
1124 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421125 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521126 request.method = "GET";
bncce36dca22015-04-21 22:11:231127 request.url = GURL("http://www.example.org/");
initial.commit586acc5fe2008-07-26 22:42:521128 request.load_flags = 0;
1129
[email protected]262eec82013-03-19 21:01:361130 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501131 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271132
[email protected]49639fa2011-12-20 23:22:411133 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521134
[email protected]49639fa2011-12-20 23:22:411135 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421136 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521137
1138 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421139 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521140
[email protected]1c773ea12009-04-28 19:58:421141 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501142 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521143
[email protected]90499482013-06-01 00:39:501144 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251145 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151146 EXPECT_TRUE(response->proxy_server.IsEmpty());
initial.commit586acc5fe2008-07-26 22:42:521147
1148 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571149 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421150 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251151 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521152 }
1153}
1154
[email protected]23e482282013-06-14 16:08:021155TEST_P(HttpNetworkTransactionTest, Ignores100) {
[email protected]b2d26cfd2012-12-11 10:36:061156 ScopedVector<UploadElementReader> element_readers;
1157 element_readers.push_back(new UploadBytesElementReader("foo", 3));
mmenkecbc2b712014-10-09 20:29:071158 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]329b68b2012-11-14 17:54:271159
[email protected]1c773ea12009-04-28 19:58:421160 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521161 request.method = "POST";
1162 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271163 request.upload_data_stream = &upload_data_stream;
initial.commit586acc5fe2008-07-26 22:42:521164 request.load_flags = 0;
1165
mmenke6b3af6e2015-09-12 02:06:061166 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271167 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411168 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271169
initial.commit586acc5fe2008-07-26 22:42:521170 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351171 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1172 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1173 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061174 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521175 };
[email protected]31a2bfe2010-02-09 08:03:391176 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071177 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521178
[email protected]49639fa2011-12-20 23:22:411179 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521180
[email protected]49639fa2011-12-20 23:22:411181 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421182 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521183
1184 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421185 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521186
[email protected]1c773ea12009-04-28 19:58:421187 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501188 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521189
[email protected]90499482013-06-01 00:39:501190 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251191 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521192
1193 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571194 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421195 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251196 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521197}
1198
[email protected]3a2d3662009-03-27 03:49:141199// This test is almost the same as Ignores100 above, but the response contains
1200// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571201// HTTP/1.1 and the two status headers are read in one read.
[email protected]23e482282013-06-14 16:08:021202TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421203 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141204 request.method = "GET";
1205 request.url = GURL("http://www.foo.com/");
1206 request.load_flags = 0;
1207
mmenke6b3af6e2015-09-12 02:06:061208 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271209 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411210 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271211
[email protected]3a2d3662009-03-27 03:49:141212 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571213 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1214 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141215 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061216 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141217 };
[email protected]31a2bfe2010-02-09 08:03:391218 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071219 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141220
[email protected]49639fa2011-12-20 23:22:411221 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141222
[email protected]49639fa2011-12-20 23:22:411223 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421224 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:141225
1226 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421227 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:141228
[email protected]1c773ea12009-04-28 19:58:421229 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501230 ASSERT_TRUE(response != NULL);
[email protected]3a2d3662009-03-27 03:49:141231
[email protected]90499482013-06-01 00:39:501232 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3a2d3662009-03-27 03:49:141233 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1234
1235 std::string response_data;
1236 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421237 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:141238 EXPECT_EQ("hello world", response_data);
1239}
1240
[email protected]23e482282013-06-14 16:08:021241TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081242 HttpRequestInfo request;
1243 request.method = "POST";
1244 request.url = GURL("http://www.foo.com/");
1245 request.load_flags = 0;
1246
mmenke6b3af6e2015-09-12 02:06:061247 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
zmo9528c9f42015-08-04 22:12:081248 scoped_ptr<HttpTransaction> trans(
1249 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1250
1251 MockRead data_reads[] = {
1252 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1253 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381254 };
zmo9528c9f42015-08-04 22:12:081255 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1256 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381257
zmo9528c9f42015-08-04 22:12:081258 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381259
zmo9528c9f42015-08-04 22:12:081260 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1261 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ee9410e72010-01-07 01:42:381262
zmo9528c9f42015-08-04 22:12:081263 rv = callback.WaitForResult();
1264 EXPECT_EQ(OK, rv);
[email protected]ee9410e72010-01-07 01:42:381265
zmo9528c9f42015-08-04 22:12:081266 std::string response_data;
1267 rv = ReadTransaction(trans.get(), &response_data);
1268 EXPECT_EQ(OK, rv);
1269 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381270}
1271
[email protected]23e482282013-06-14 16:08:021272TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381273 HttpRequestInfo request;
1274 request.method = "POST";
1275 request.url = GURL("http://www.foo.com/");
1276 request.load_flags = 0;
1277
mmenke6b3af6e2015-09-12 02:06:061278 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271279 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411280 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271281
[email protected]ee9410e72010-01-07 01:42:381282 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061283 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381284 };
[email protected]31a2bfe2010-02-09 08:03:391285 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071286 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381287
[email protected]49639fa2011-12-20 23:22:411288 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381289
[email protected]49639fa2011-12-20 23:22:411290 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:381291 EXPECT_EQ(ERR_IO_PENDING, rv);
1292
1293 rv = callback.WaitForResult();
1294 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1295}
1296
[email protected]23e482282013-06-14 16:08:021297void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511298 const MockWrite* write_failure,
1299 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421300 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521301 request.method = "GET";
1302 request.url = GURL("http://www.foo.com/");
1303 request.load_flags = 0;
1304
vishal.b62985ca92015-04-17 08:45:511305 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071306 session_deps_.net_log = &net_log;
mmenke6b3af6e2015-09-12 02:06:061307 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271308
[email protected]202965992011-12-07 23:04:511309 // Written data for successfully sending both requests.
1310 MockWrite data1_writes[] = {
1311 MockWrite("GET / HTTP/1.1\r\n"
1312 "Host: www.foo.com\r\n"
1313 "Connection: keep-alive\r\n\r\n"),
1314 MockWrite("GET / HTTP/1.1\r\n"
1315 "Host: www.foo.com\r\n"
1316 "Connection: keep-alive\r\n\r\n")
1317 };
1318
1319 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521320 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351321 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1322 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061323 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521324 };
[email protected]202965992011-12-07 23:04:511325
1326 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491327 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511328 data1_writes[1] = *write_failure;
1329 } else {
1330 ASSERT_TRUE(read_failure);
1331 data1_reads[2] = *read_failure;
1332 }
1333
1334 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1335 data1_writes, arraysize(data1_writes));
[email protected]bb88e1d32013-05-03 23:11:071336 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521337
1338 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351339 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1340 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061341 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521342 };
[email protected]31a2bfe2010-02-09 08:03:391343 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071344 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521345
thestig9d3bb0c2015-01-24 00:49:511346 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521347 "hello", "world"
1348 };
1349
[email protected]58e32bb2013-01-21 18:23:251350 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521351 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411352 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521353
[email protected]262eec82013-03-19 21:01:361354 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501355 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
initial.commit586acc5fe2008-07-26 22:42:521356
[email protected]49639fa2011-12-20 23:22:411357 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421358 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521359
1360 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421361 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521362
[email protected]58e32bb2013-01-21 18:23:251363 LoadTimingInfo load_timing_info;
1364 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1365 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1366 if (i == 0) {
1367 first_socket_log_id = load_timing_info.socket_log_id;
1368 } else {
1369 // The second request should be using a new socket.
1370 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1371 }
1372
[email protected]1c773ea12009-04-28 19:58:421373 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501374 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521375
[email protected]90499482013-06-01 00:39:501376 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251377 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521378
1379 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571380 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421381 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251382 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521383 }
1384}
[email protected]3d2a59b2008-09-26 19:44:251385
[email protected]a34f61ee2014-03-18 20:59:491386void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1387 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101388 const MockRead* read_failure,
1389 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491390 HttpRequestInfo request;
1391 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101392 request.url = GURL("https://www.foo.com/");
[email protected]a34f61ee2014-03-18 20:59:491393 request.load_flags = 0;
1394
vishal.b62985ca92015-04-17 08:45:511395 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491396 session_deps_.net_log = &net_log;
mmenke6b3af6e2015-09-12 02:06:061397 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491398
[email protected]09356c652014-03-25 15:36:101399 SSLSocketDataProvider ssl1(ASYNC, OK);
1400 SSLSocketDataProvider ssl2(ASYNC, OK);
1401 if (use_spdy) {
1402 ssl1.SetNextProto(GetParam());
1403 ssl2.SetNextProto(GetParam());
1404 }
1405 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1406 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491407
[email protected]09356c652014-03-25 15:36:101408 // SPDY versions of the request and response.
1409 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1410 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1411 scoped_ptr<SpdyFrame> spdy_response(
1412 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1413 scoped_ptr<SpdyFrame> spdy_data(
1414 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
[email protected]a34f61ee2014-03-18 20:59:491415
[email protected]09356c652014-03-25 15:36:101416 // HTTP/1.1 versions of the request and response.
1417 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1418 "Host: www.foo.com\r\n"
1419 "Connection: keep-alive\r\n\r\n";
1420 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1421 const char kHttpData[] = "hello";
1422
1423 std::vector<MockRead> data1_reads;
1424 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491425 if (write_failure) {
1426 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101427 data1_writes.push_back(*write_failure);
1428 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491429 } else {
1430 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101431 if (use_spdy) {
1432 data1_writes.push_back(CreateMockWrite(*spdy_request));
1433 } else {
1434 data1_writes.push_back(MockWrite(kHttpRequest));
1435 }
1436 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491437 }
1438
[email protected]09356c652014-03-25 15:36:101439 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1440 &data1_writes[0], data1_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491441 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1442
[email protected]09356c652014-03-25 15:36:101443 std::vector<MockRead> data2_reads;
1444 std::vector<MockWrite> data2_writes;
1445
1446 if (use_spdy) {
1447 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1448
1449 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1450 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1451 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1452 } else {
1453 data2_writes.push_back(
1454 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1455
1456 data2_reads.push_back(
1457 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1458 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1459 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1460 }
rch8e6c6c42015-05-01 14:05:131461 SequencedSocketData data2(&data2_reads[0], data2_reads.size(),
1462 &data2_writes[0], data2_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491463 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1464
1465 // Preconnect a socket.
ttuttle859dc7a2015-04-23 19:42:291466 SSLConfig ssl_config;
[email protected]a34f61ee2014-03-18 20:59:491467 session->ssl_config_service()->GetSSLConfig(&ssl_config);
[email protected]d7599122014-05-24 03:37:231468 session->GetNextProtos(&ssl_config.next_protos);
mmenked1205bd2015-07-15 22:26:351469 session->http_stream_factory()->PreconnectStreams(1, request, ssl_config,
1470 ssl_config);
[email protected]a34f61ee2014-03-18 20:59:491471 // Wait for the preconnect to complete.
1472 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1473 base::RunLoop().RunUntilIdle();
[email protected]09356c652014-03-25 15:36:101474 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491475
1476 // Make the request.
1477 TestCompletionCallback callback;
1478
1479 scoped_ptr<HttpTransaction> trans(
1480 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1481
1482 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1483 EXPECT_EQ(ERR_IO_PENDING, rv);
1484
1485 rv = callback.WaitForResult();
1486 EXPECT_EQ(OK, rv);
1487
1488 LoadTimingInfo load_timing_info;
1489 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101490 TestLoadTimingNotReused(
1491 load_timing_info,
1492 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491493
1494 const HttpResponseInfo* response = trans->GetResponseInfo();
1495 ASSERT_TRUE(response != NULL);
1496
1497 EXPECT_TRUE(response->headers.get() != NULL);
1498 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1499
1500 std::string response_data;
1501 rv = ReadTransaction(trans.get(), &response_data);
1502 EXPECT_EQ(OK, rv);
[email protected]09356c652014-03-25 15:36:101503 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491504}
1505
[email protected]23e482282013-06-14 16:08:021506TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:231507 KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061508 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]202965992011-12-07 23:04:511509 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1510}
1511
[email protected]23e482282013-06-14 16:08:021512TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061513 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]202965992011-12-07 23:04:511514 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251515}
1516
[email protected]23e482282013-06-14 16:08:021517TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061518 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]202965992011-12-07 23:04:511519 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251520}
1521
[email protected]d58ceea82014-06-04 10:55:541522// Make sure that on a 408 response (Request Timeout), the request is retried,
1523// if the socket was a reused keep alive socket.
1524TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1525 MockRead read_failure(SYNCHRONOUS,
1526 "HTTP/1.1 408 Request Timeout\r\n"
1527 "Connection: Keep-Alive\r\n"
1528 "Content-Length: 6\r\n\r\n"
1529 "Pickle");
1530 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1531}
1532
[email protected]a34f61ee2014-03-18 20:59:491533TEST_P(HttpNetworkTransactionTest,
1534 PreconnectErrorNotConnectedOnWrite) {
1535 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]09356c652014-03-25 15:36:101536 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
[email protected]a34f61ee2014-03-18 20:59:491537}
1538
1539TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1540 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]09356c652014-03-25 15:36:101541 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491542}
1543
1544TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1545 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]09356c652014-03-25 15:36:101546 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1547}
1548
1549TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1550 MockRead read_failure(ASYNC, OK); // EOF
1551 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1552}
1553
[email protected]d58ceea82014-06-04 10:55:541554// Make sure that on a 408 response (Request Timeout), the request is retried,
1555// if the socket was a preconnected (UNUSED_IDLE) socket.
1556TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1557 MockRead read_failure(SYNCHRONOUS,
1558 "HTTP/1.1 408 Request Timeout\r\n"
1559 "Connection: Keep-Alive\r\n"
1560 "Content-Length: 6\r\n\r\n"
1561 "Pickle");
1562 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1563 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1564}
1565
[email protected]09356c652014-03-25 15:36:101566TEST_P(HttpNetworkTransactionTest,
1567 SpdyPreconnectErrorNotConnectedOnWrite) {
1568 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1569 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1570}
1571
1572TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1573 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1574 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1575}
1576
1577TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1578 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1579 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1580}
1581
1582TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1583 MockRead read_failure(ASYNC, OK); // EOF
1584 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:491585}
1586
[email protected]23e482282013-06-14 16:08:021587TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421588 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251589 request.method = "GET";
bncce36dca22015-04-21 22:11:231590 request.url = GURL("http://www.example.org/");
[email protected]3d2a59b2008-09-26 19:44:251591 request.load_flags = 0;
1592
mmenke6b3af6e2015-09-12 02:06:061593 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271594 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411595 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271596
[email protected]3d2a59b2008-09-26 19:44:251597 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061598 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:351599 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1600 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061601 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251602 };
[email protected]31a2bfe2010-02-09 08:03:391603 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071604 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:251605
[email protected]49639fa2011-12-20 23:22:411606 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:251607
[email protected]49639fa2011-12-20 23:22:411608 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421609 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:251610
1611 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421612 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
ttuttled9dbc652015-09-29 20:00:591613
1614 IPEndPoint endpoint;
1615 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
1616 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:251617}
1618
1619// What do various browsers do when the server closes a non-keepalive
1620// connection without sending any response header or body?
1621//
1622// IE7: error page
1623// Safari 3.1.2 (Windows): error page
1624// Firefox 3.0.1: blank page
1625// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:421626// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1627// Us: error page (EMPTY_RESPONSE)
[email protected]23e482282013-06-14 16:08:021628TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:251629 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061630 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:351631 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1632 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061633 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251634 };
[email protected]31a2bfe2010-02-09 08:03:391635 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1636 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:421637 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:251638}
[email protected]038e9a32008-10-08 22:40:161639
[email protected]1826a402014-01-08 15:40:481640// Test that network access can be deferred and resumed.
1641TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1642 HttpRequestInfo request;
1643 request.method = "GET";
bncce36dca22015-04-21 22:11:231644 request.url = GURL("http://www.example.org/");
[email protected]1826a402014-01-08 15:40:481645 request.load_flags = 0;
1646
mmenke6b3af6e2015-09-12 02:06:061647 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1826a402014-01-08 15:40:481648 scoped_ptr<HttpTransaction> trans(
1649 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1650
1651 // Defer on OnBeforeNetworkStart.
1652 BeforeNetworkStartHandler net_start_handler(true); // defer
1653 trans->SetBeforeNetworkStartCallback(
1654 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1655 base::Unretained(&net_start_handler)));
1656
1657 MockRead data_reads[] = {
1658 MockRead("HTTP/1.0 200 OK\r\n"),
1659 MockRead("Content-Length: 5\r\n\r\n"),
1660 MockRead("hello"),
1661 MockRead(SYNCHRONOUS, 0),
1662 };
1663 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1664 session_deps_.socket_factory->AddSocketDataProvider(&data);
1665
1666 TestCompletionCallback callback;
1667
1668 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1669 EXPECT_EQ(ERR_IO_PENDING, rv);
1670 base::MessageLoop::current()->RunUntilIdle();
1671
1672 // Should have deferred for network start.
1673 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1674 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
[email protected]1826a402014-01-08 15:40:481675
1676 trans->ResumeNetworkStart();
1677 rv = callback.WaitForResult();
1678 EXPECT_EQ(OK, rv);
1679 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1680
1681 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1682 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1683 if (rv == ERR_IO_PENDING)
1684 rv = callback.WaitForResult();
1685 EXPECT_EQ(5, rv);
1686 trans.reset();
1687}
1688
1689// Test that network use can be deferred and canceled.
1690TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1691 HttpRequestInfo request;
1692 request.method = "GET";
bncce36dca22015-04-21 22:11:231693 request.url = GURL("http://www.example.org/");
[email protected]1826a402014-01-08 15:40:481694 request.load_flags = 0;
1695
mmenke6b3af6e2015-09-12 02:06:061696 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1826a402014-01-08 15:40:481697 scoped_ptr<HttpTransaction> trans(
1698 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1699
1700 // Defer on OnBeforeNetworkStart.
1701 BeforeNetworkStartHandler net_start_handler(true); // defer
1702 trans->SetBeforeNetworkStartCallback(
1703 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1704 base::Unretained(&net_start_handler)));
1705
1706 TestCompletionCallback callback;
1707
1708 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1709 EXPECT_EQ(ERR_IO_PENDING, rv);
1710 base::MessageLoop::current()->RunUntilIdle();
1711
1712 // Should have deferred for network start.
1713 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1714 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
[email protected]1826a402014-01-08 15:40:481715}
1716
[email protected]7a5378b2012-11-04 03:25:171717// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1718// tests. There was a bug causing HttpNetworkTransaction to hang in the
1719// destructor in such situations.
1720// See http://crbug.com/154712 and http://crbug.com/156609.
[email protected]23e482282013-06-14 16:08:021721TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:171722 HttpRequestInfo request;
1723 request.method = "GET";
bncce36dca22015-04-21 22:11:231724 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171725 request.load_flags = 0;
1726
mmenke6b3af6e2015-09-12 02:06:061727 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:361728 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501729 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171730
1731 MockRead data_reads[] = {
1732 MockRead("HTTP/1.0 200 OK\r\n"),
1733 MockRead("Connection: keep-alive\r\n"),
1734 MockRead("Content-Length: 100\r\n\r\n"),
1735 MockRead("hello"),
1736 MockRead(SYNCHRONOUS, 0),
1737 };
1738 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071739 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171740
1741 TestCompletionCallback callback;
1742
1743 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1744 EXPECT_EQ(ERR_IO_PENDING, rv);
1745
1746 rv = callback.WaitForResult();
1747 EXPECT_EQ(OK, rv);
1748
1749 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501750 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171751 if (rv == ERR_IO_PENDING)
1752 rv = callback.WaitForResult();
1753 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:501754 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171755 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1756
1757 trans.reset();
[email protected]2da659e2013-05-23 20:51:341758 base::MessageLoop::current()->RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171759 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1760}
1761
[email protected]23e482282013-06-14 16:08:021762TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:171763 HttpRequestInfo request;
1764 request.method = "GET";
bncce36dca22015-04-21 22:11:231765 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171766 request.load_flags = 0;
1767
mmenke6b3af6e2015-09-12 02:06:061768 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:361769 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501770 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171771
1772 MockRead data_reads[] = {
1773 MockRead("HTTP/1.0 200 OK\r\n"),
1774 MockRead("Connection: keep-alive\r\n"),
1775 MockRead("Content-Length: 100\r\n\r\n"),
1776 MockRead(SYNCHRONOUS, 0),
1777 };
1778 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071779 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171780
1781 TestCompletionCallback callback;
1782
1783 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1784 EXPECT_EQ(ERR_IO_PENDING, rv);
1785
1786 rv = callback.WaitForResult();
1787 EXPECT_EQ(OK, rv);
1788
1789 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501790 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171791 if (rv == ERR_IO_PENDING)
1792 rv = callback.WaitForResult();
1793 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1794
1795 trans.reset();
[email protected]2da659e2013-05-23 20:51:341796 base::MessageLoop::current()->RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171797 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1798}
1799
[email protected]0b0bf032010-09-21 18:08:501800// Test that we correctly reuse a keep-alive connection after not explicitly
1801// reading the body.
[email protected]23e482282013-06-14 16:08:021802TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:131803 HttpRequestInfo request;
1804 request.method = "GET";
1805 request.url = GURL("http://www.foo.com/");
1806 request.load_flags = 0;
1807
vishal.b62985ca92015-04-17 08:45:511808 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071809 session_deps_.net_log = &net_log;
mmenke6b3af6e2015-09-12 02:06:061810 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271811
[email protected]0b0bf032010-09-21 18:08:501812 // Note that because all these reads happen in the same
1813 // StaticSocketDataProvider, it shows that the same socket is being reused for
1814 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:131815 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:501816 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1817 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:131818 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:501819 MockRead("HTTP/1.1 302 Found\r\n"
1820 "Content-Length: 0\r\n\r\n"),
1821 MockRead("HTTP/1.1 302 Found\r\n"
1822 "Content-Length: 5\r\n\r\n"
1823 "hello"),
1824 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1825 "Content-Length: 0\r\n\r\n"),
1826 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1827 "Content-Length: 5\r\n\r\n"
1828 "hello"),
[email protected]fc31d6a42010-06-24 18:05:131829 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1830 MockRead("hello"),
1831 };
1832 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071833 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]fc31d6a42010-06-24 18:05:131834
1835 MockRead data2_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061836 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
[email protected]fc31d6a42010-06-24 18:05:131837 };
1838 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071839 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]fc31d6a42010-06-24 18:05:131840
[email protected]0b0bf032010-09-21 18:08:501841 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1842 std::string response_lines[kNumUnreadBodies];
1843
[email protected]58e32bb2013-01-21 18:23:251844 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
[email protected]0b0bf032010-09-21 18:08:501845 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411846 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:131847
[email protected]262eec82013-03-19 21:01:361848 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501849 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]fc31d6a42010-06-24 18:05:131850
[email protected]49639fa2011-12-20 23:22:411851 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]fc31d6a42010-06-24 18:05:131852 EXPECT_EQ(ERR_IO_PENDING, rv);
1853
1854 rv = callback.WaitForResult();
1855 EXPECT_EQ(OK, rv);
1856
[email protected]58e32bb2013-01-21 18:23:251857 LoadTimingInfo load_timing_info;
1858 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1859 if (i == 0) {
1860 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1861 first_socket_log_id = load_timing_info.socket_log_id;
1862 } else {
1863 TestLoadTimingReused(load_timing_info);
1864 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1865 }
1866
[email protected]fc31d6a42010-06-24 18:05:131867 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:501868 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:131869
[email protected]90499482013-06-01 00:39:501870 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]0b0bf032010-09-21 18:08:501871 response_lines[i] = response->headers->GetStatusLine();
1872
1873 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:131874 }
[email protected]0b0bf032010-09-21 18:08:501875
1876 const char* const kStatusLines[] = {
1877 "HTTP/1.1 204 No Content",
1878 "HTTP/1.1 205 Reset Content",
1879 "HTTP/1.1 304 Not Modified",
1880 "HTTP/1.1 302 Found",
1881 "HTTP/1.1 302 Found",
1882 "HTTP/1.1 301 Moved Permanently",
1883 "HTTP/1.1 301 Moved Permanently",
1884 };
1885
mostynb91e0da982015-01-20 19:17:271886 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1887 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:501888
1889 for (int i = 0; i < kNumUnreadBodies; ++i)
1890 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1891
[email protected]49639fa2011-12-20 23:22:411892 TestCompletionCallback callback;
[email protected]262eec82013-03-19 21:01:361893 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501894 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:411895 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0b0bf032010-09-21 18:08:501896 EXPECT_EQ(ERR_IO_PENDING, rv);
1897 rv = callback.WaitForResult();
1898 EXPECT_EQ(OK, rv);
1899 const HttpResponseInfo* response = trans->GetResponseInfo();
1900 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:501901 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]0b0bf032010-09-21 18:08:501902 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1903 std::string response_data;
1904 rv = ReadTransaction(trans.get(), &response_data);
1905 EXPECT_EQ(OK, rv);
1906 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131907}
1908
[email protected]038e9a32008-10-08 22:40:161909// Test the request-challenge-retry sequence for basic auth.
1910// (basic auth is the easiest to mock, because it has no randomness).
[email protected]23e482282013-06-14 16:08:021911TEST_P(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421912 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161913 request.method = "GET";
bncce36dca22015-04-21 22:11:231914 request.url = GURL("http://www.example.org/");
[email protected]038e9a32008-10-08 22:40:161915 request.load_flags = 0;
1916
vishal.b62985ca92015-04-17 08:45:511917 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:071918 session_deps_.net_log = &log;
mmenke6b3af6e2015-09-12 02:06:061919 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271920 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411921 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271922
[email protected]f9ee6b52008-11-08 06:46:231923 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:231924 MockWrite(
1925 "GET / HTTP/1.1\r\n"
1926 "Host: www.example.org\r\n"
1927 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:231928 };
1929
[email protected]038e9a32008-10-08 22:40:161930 MockRead data_reads1[] = {
1931 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1932 // Give a couple authenticate options (only the middle one is actually
1933 // supported).
[email protected]22927ad2009-09-21 19:56:191934 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161935 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1936 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1937 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1938 // Large content-length -- won't matter, as connection will be reset.
1939 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061940 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161941 };
1942
1943 // After calling trans->RestartWithAuth(), this is the request we should
1944 // be issuing -- the final header line contains the credentials.
1945 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:231946 MockWrite(
1947 "GET / HTTP/1.1\r\n"
1948 "Host: www.example.org\r\n"
1949 "Connection: keep-alive\r\n"
1950 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:161951 };
1952
1953 // Lastly, the server responds with the actual content.
1954 MockRead data_reads2[] = {
1955 MockRead("HTTP/1.0 200 OK\r\n"),
1956 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1957 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061958 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:161959 };
1960
[email protected]31a2bfe2010-02-09 08:03:391961 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1962 data_writes1, arraysize(data_writes1));
1963 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1964 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:071965 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1966 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161967
[email protected]49639fa2011-12-20 23:22:411968 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:161969
[email protected]49639fa2011-12-20 23:22:411970 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421971 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161972
1973 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421974 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161975
[email protected]58e32bb2013-01-21 18:23:251976 LoadTimingInfo load_timing_info1;
1977 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1978 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1979
sclittlefb249892015-09-10 21:33:221980 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
1981 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
1982 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
[email protected]b8015c42013-12-24 15:18:191983 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1984
[email protected]1c773ea12009-04-28 19:58:421985 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501986 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041987 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:161988
[email protected]49639fa2011-12-20 23:22:411989 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:161990
[email protected]49639fa2011-12-20 23:22:411991 rv = trans->RestartWithAuth(
1992 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:421993 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161994
1995 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421996 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161997
[email protected]58e32bb2013-01-21 18:23:251998 LoadTimingInfo load_timing_info2;
1999 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2000 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2001 // The load timing after restart should have a new socket ID, and times after
2002 // those of the first load timing.
2003 EXPECT_LE(load_timing_info1.receive_headers_end,
2004 load_timing_info2.connect_timing.connect_start);
2005 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2006
sclittlefb249892015-09-10 21:33:222007 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2008 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2009 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
[email protected]b8015c42013-12-24 15:18:192010 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2011
[email protected]038e9a32008-10-08 22:40:162012 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502013 ASSERT_TRUE(response != NULL);
[email protected]038e9a32008-10-08 22:40:162014 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2015 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162016}
2017
ttuttled9dbc652015-09-29 20:00:592018// Test the request-challenge-retry sequence for basic auth.
2019// (basic auth is the easiest to mock, because it has no randomness).
2020TEST_P(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
2021 HttpRequestInfo request;
2022 request.method = "GET";
2023 request.url = GURL("http://www.example.org/");
2024 request.load_flags = 0;
2025
2026 TestNetLog log;
2027 MockHostResolver* resolver = new MockHostResolver();
2028 session_deps_.net_log = &log;
2029 session_deps_.host_resolver.reset(resolver);
2030 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2031 scoped_ptr<HttpTransaction> trans(
2032 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2033
2034 resolver->rules()->ClearRules();
2035 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2036
2037 MockWrite data_writes1[] = {
2038 MockWrite("GET / HTTP/1.1\r\n"
2039 "Host: www.example.org\r\n"
2040 "Connection: keep-alive\r\n\r\n"),
2041 };
2042
2043 MockRead data_reads1[] = {
2044 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2045 // Give a couple authenticate options (only the middle one is actually
2046 // supported).
2047 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2048 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2049 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2050 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2051 // Large content-length -- won't matter, as connection will be reset.
2052 MockRead("Content-Length: 10000\r\n\r\n"),
2053 MockRead(SYNCHRONOUS, ERR_FAILED),
2054 };
2055
2056 // After calling trans->RestartWithAuth(), this is the request we should
2057 // be issuing -- the final header line contains the credentials.
2058 MockWrite data_writes2[] = {
2059 MockWrite("GET / HTTP/1.1\r\n"
2060 "Host: www.example.org\r\n"
2061 "Connection: keep-alive\r\n"
2062 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2063 };
2064
2065 // Lastly, the server responds with the actual content.
2066 MockRead data_reads2[] = {
2067 MockRead("HTTP/1.0 200 OK\r\n"),
2068 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2069 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2070 };
2071
2072 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2073 data_writes1, arraysize(data_writes1));
2074 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2075 data_writes2, arraysize(data_writes2));
2076 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2077 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2078
2079 TestCompletionCallback callback1;
2080
2081 EXPECT_EQ(OK, callback1.GetResult(trans->Start(&request, callback1.callback(),
2082 BoundNetLog())));
2083
2084 LoadTimingInfo load_timing_info1;
2085 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2086 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2087
2088 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2089 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2090 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
2091 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2092
2093 const HttpResponseInfo* response = trans->GetResponseInfo();
2094 ASSERT_TRUE(response);
2095 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2096
2097 IPEndPoint endpoint;
2098 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2099 ASSERT_FALSE(endpoint.address().empty());
2100 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2101
2102 resolver->rules()->ClearRules();
2103 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2104
2105 TestCompletionCallback callback2;
2106
2107 EXPECT_EQ(OK, callback2.GetResult(trans->RestartWithAuth(
2108 AuthCredentials(kFoo, kBar), callback2.callback())));
2109
2110 LoadTimingInfo load_timing_info2;
2111 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2112 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2113 // The load timing after restart should have a new socket ID, and times after
2114 // those of the first load timing.
2115 EXPECT_LE(load_timing_info1.receive_headers_end,
2116 load_timing_info2.connect_timing.connect_start);
2117 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2118
2119 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2120 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2121 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
2122 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2123
2124 response = trans->GetResponseInfo();
2125 ASSERT_TRUE(response);
2126 EXPECT_FALSE(response->auth_challenge.get());
2127 EXPECT_EQ(100, response->headers->GetContentLength());
2128
2129 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2130 ASSERT_FALSE(endpoint.address().empty());
2131 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2132}
2133
[email protected]23e482282013-06-14 16:08:022134TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462135 HttpRequestInfo request;
2136 request.method = "GET";
bncce36dca22015-04-21 22:11:232137 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292138 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]861fcd52009-08-26 02:33:462139
mmenke6b3af6e2015-09-12 02:06:062140 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272141 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:412142 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:272143
[email protected]861fcd52009-08-26 02:33:462144 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232145 MockWrite(
2146 "GET / HTTP/1.1\r\n"
2147 "Host: www.example.org\r\n"
2148 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462149 };
2150
2151 MockRead data_reads[] = {
2152 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2153 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2154 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2155 // Large content-length -- won't matter, as connection will be reset.
2156 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062157 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462158 };
2159
[email protected]31a2bfe2010-02-09 08:03:392160 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2161 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:072162 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412163 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462164
[email protected]49639fa2011-12-20 23:22:412165 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]861fcd52009-08-26 02:33:462166 EXPECT_EQ(ERR_IO_PENDING, rv);
2167
2168 rv = callback.WaitForResult();
2169 EXPECT_EQ(0, rv);
2170
sclittlefb249892015-09-10 21:33:222171 int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes));
2172 EXPECT_EQ(writes_size, trans->GetTotalSentBytes());
2173 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
[email protected]b8015c42013-12-24 15:18:192174 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2175
[email protected]861fcd52009-08-26 02:33:462176 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502177 ASSERT_TRUE(response != NULL);
[email protected]861fcd52009-08-26 02:33:462178 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2179}
2180
[email protected]2d2697f92009-02-18 21:00:322181// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2182// connection.
[email protected]23e482282013-06-14 16:08:022183TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]1c773ea12009-04-28 19:58:422184 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322185 request.method = "GET";
bncce36dca22015-04-21 22:11:232186 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322187 request.load_flags = 0;
2188
vishal.b62985ca92015-04-17 08:45:512189 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072190 session_deps_.net_log = &log;
mmenke6b3af6e2015-09-12 02:06:062191 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272192
[email protected]2d2697f92009-02-18 21:00:322193 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232194 MockWrite(
2195 "GET / HTTP/1.1\r\n"
2196 "Host: www.example.org\r\n"
2197 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322198
bncce36dca22015-04-21 22:11:232199 // After calling trans->RestartWithAuth(), this is the request we should
2200 // be issuing -- the final header line contains the credentials.
2201 MockWrite(
2202 "GET / HTTP/1.1\r\n"
2203 "Host: www.example.org\r\n"
2204 "Connection: keep-alive\r\n"
2205 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322206 };
2207
2208 MockRead data_reads1[] = {
2209 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2210 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2211 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2212 MockRead("Content-Length: 14\r\n\r\n"),
2213 MockRead("Unauthorized\r\n"),
2214
2215 // Lastly, the server responds with the actual content.
2216 MockRead("HTTP/1.1 200 OK\r\n"),
2217 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502218 MockRead("Content-Length: 5\r\n\r\n"),
2219 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:322220 };
2221
[email protected]2d0a4f92011-05-05 16:38:462222 // If there is a regression where we disconnect a Keep-Alive
2223 // connection during an auth roundtrip, we'll end up reading this.
2224 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062225 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462226 };
2227
[email protected]31a2bfe2010-02-09 08:03:392228 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2229 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462230 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2231 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072232 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2233 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322234
[email protected]49639fa2011-12-20 23:22:412235 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322236
[email protected]262eec82013-03-19 21:01:362237 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502238 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412239 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422240 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322241
2242 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422243 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322244
[email protected]58e32bb2013-01-21 18:23:252245 LoadTimingInfo load_timing_info1;
2246 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2247 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2248
[email protected]1c773ea12009-04-28 19:58:422249 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502250 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042251 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322252
[email protected]49639fa2011-12-20 23:22:412253 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322254
[email protected]49639fa2011-12-20 23:22:412255 rv = trans->RestartWithAuth(
2256 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422257 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322258
2259 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422260 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322261
[email protected]58e32bb2013-01-21 18:23:252262 LoadTimingInfo load_timing_info2;
2263 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2264 TestLoadTimingReused(load_timing_info2);
2265 // The load timing after restart should have the same socket ID, and times
2266 // those of the first load timing.
2267 EXPECT_LE(load_timing_info1.receive_headers_end,
2268 load_timing_info2.send_start);
2269 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2270
[email protected]2d2697f92009-02-18 21:00:322271 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502272 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322273 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502274 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]b8015c42013-12-24 15:18:192275
2276 std::string response_data;
2277 rv = ReadTransaction(trans.get(), &response_data);
2278 EXPECT_EQ(OK, rv);
sclittlefb249892015-09-10 21:33:222279
2280 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2281 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2282 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
[email protected]b8015c42013-12-24 15:18:192283 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
[email protected]2d2697f92009-02-18 21:00:322284}
2285
2286// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2287// connection and with no response body to drain.
[email protected]23e482282013-06-14 16:08:022288TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:422289 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322290 request.method = "GET";
bncce36dca22015-04-21 22:11:232291 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322292 request.load_flags = 0;
2293
mmenke6b3af6e2015-09-12 02:06:062294 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272295
[email protected]2d2697f92009-02-18 21:00:322296 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232297 MockWrite(
2298 "GET / HTTP/1.1\r\n"
2299 "Host: www.example.org\r\n"
2300 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322301
bncce36dca22015-04-21 22:11:232302 // After calling trans->RestartWithAuth(), this is the request we should
2303 // be issuing -- the final header line contains the credentials.
2304 MockWrite(
2305 "GET / HTTP/1.1\r\n"
2306 "Host: www.example.org\r\n"
2307 "Connection: keep-alive\r\n"
2308 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322309 };
2310
[email protected]2d2697f92009-02-18 21:00:322311 MockRead data_reads1[] = {
2312 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2313 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:312314 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:322315
2316 // Lastly, the server responds with the actual content.
2317 MockRead("HTTP/1.1 200 OK\r\n"),
2318 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502319 MockRead("Content-Length: 5\r\n\r\n"),
2320 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322321 };
2322
[email protected]2d0a4f92011-05-05 16:38:462323 // An incorrect reconnect would cause this to be read.
2324 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062325 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462326 };
2327
[email protected]31a2bfe2010-02-09 08:03:392328 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2329 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462330 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2331 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072332 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2333 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322334
[email protected]49639fa2011-12-20 23:22:412335 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322336
[email protected]262eec82013-03-19 21:01:362337 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502338 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412339 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422340 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322341
2342 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422343 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322344
[email protected]1c773ea12009-04-28 19:58:422345 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502346 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042347 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322348
[email protected]49639fa2011-12-20 23:22:412349 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322350
[email protected]49639fa2011-12-20 23:22:412351 rv = trans->RestartWithAuth(
2352 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422353 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322354
2355 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422356 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322357
2358 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502359 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322360 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502361 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322362}
2363
2364// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2365// connection and with a large response body to drain.
[email protected]23e482282013-06-14 16:08:022366TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:422367 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322368 request.method = "GET";
bncce36dca22015-04-21 22:11:232369 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322370 request.load_flags = 0;
2371
mmenke6b3af6e2015-09-12 02:06:062372 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272373
[email protected]2d2697f92009-02-18 21:00:322374 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232375 MockWrite(
2376 "GET / HTTP/1.1\r\n"
2377 "Host: www.example.org\r\n"
2378 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322379
bncce36dca22015-04-21 22:11:232380 // After calling trans->RestartWithAuth(), this is the request we should
2381 // be issuing -- the final header line contains the credentials.
2382 MockWrite(
2383 "GET / HTTP/1.1\r\n"
2384 "Host: www.example.org\r\n"
2385 "Connection: keep-alive\r\n"
2386 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322387 };
2388
2389 // Respond with 5 kb of response body.
2390 std::string large_body_string("Unauthorized");
2391 large_body_string.append(5 * 1024, ' ');
2392 large_body_string.append("\r\n");
2393
2394 MockRead data_reads1[] = {
2395 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2396 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2397 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2398 // 5134 = 12 + 5 * 1024 + 2
2399 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062400 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:322401
2402 // Lastly, the server responds with the actual content.
2403 MockRead("HTTP/1.1 200 OK\r\n"),
2404 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502405 MockRead("Content-Length: 5\r\n\r\n"),
2406 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322407 };
2408
[email protected]2d0a4f92011-05-05 16:38:462409 // An incorrect reconnect would cause this to be read.
2410 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062411 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462412 };
2413
[email protected]31a2bfe2010-02-09 08:03:392414 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2415 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462416 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2417 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072418 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2419 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322420
[email protected]49639fa2011-12-20 23:22:412421 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322422
[email protected]262eec82013-03-19 21:01:362423 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502424 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412425 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422426 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322427
2428 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422429 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322430
[email protected]1c773ea12009-04-28 19:58:422431 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502432 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042433 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322434
[email protected]49639fa2011-12-20 23:22:412435 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322436
[email protected]49639fa2011-12-20 23:22:412437 rv = trans->RestartWithAuth(
2438 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422439 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322440
2441 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422442 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322443
2444 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502445 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322446 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502447 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322448}
2449
2450// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:312451// connection, but the server gets impatient and closes the connection.
[email protected]23e482282013-06-14 16:08:022452TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:312453 HttpRequestInfo request;
2454 request.method = "GET";
bncce36dca22015-04-21 22:11:232455 request.url = GURL("http://www.example.org/");
[email protected]11203f012009-11-12 23:02:312456 request.load_flags = 0;
2457
mmenke6b3af6e2015-09-12 02:06:062458 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272459
[email protected]11203f012009-11-12 23:02:312460 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232461 MockWrite(
2462 "GET / HTTP/1.1\r\n"
2463 "Host: www.example.org\r\n"
2464 "Connection: keep-alive\r\n\r\n"),
2465 // This simulates the seemingly successful write to a closed connection
2466 // if the bug is not fixed.
2467 MockWrite(
2468 "GET / HTTP/1.1\r\n"
2469 "Host: www.example.org\r\n"
2470 "Connection: keep-alive\r\n"
2471 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312472 };
2473
2474 MockRead data_reads1[] = {
2475 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2476 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2477 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2478 MockRead("Content-Length: 14\r\n\r\n"),
2479 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:062480 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:312481 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:062482 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:312483 };
2484
2485 // After calling trans->RestartWithAuth(), this is the request we should
2486 // be issuing -- the final header line contains the credentials.
2487 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232488 MockWrite(
2489 "GET / HTTP/1.1\r\n"
2490 "Host: www.example.org\r\n"
2491 "Connection: keep-alive\r\n"
2492 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312493 };
2494
2495 // Lastly, the server responds with the actual content.
2496 MockRead data_reads2[] = {
2497 MockRead("HTTP/1.1 200 OK\r\n"),
2498 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502499 MockRead("Content-Length: 5\r\n\r\n"),
2500 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:312501 };
2502
[email protected]31a2bfe2010-02-09 08:03:392503 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2504 data_writes1, arraysize(data_writes1));
2505 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2506 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:072507 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2508 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:312509
[email protected]49639fa2011-12-20 23:22:412510 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:312511
[email protected]262eec82013-03-19 21:01:362512 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502513 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412514 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]11203f012009-11-12 23:02:312515 EXPECT_EQ(ERR_IO_PENDING, rv);
2516
2517 rv = callback1.WaitForResult();
2518 EXPECT_EQ(OK, rv);
2519
2520 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502521 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042522 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]11203f012009-11-12 23:02:312523
[email protected]49639fa2011-12-20 23:22:412524 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:312525
[email protected]49639fa2011-12-20 23:22:412526 rv = trans->RestartWithAuth(
2527 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]11203f012009-11-12 23:02:312528 EXPECT_EQ(ERR_IO_PENDING, rv);
2529
2530 rv = callback2.WaitForResult();
2531 EXPECT_EQ(OK, rv);
2532
2533 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502534 ASSERT_TRUE(response != NULL);
[email protected]11203f012009-11-12 23:02:312535 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502536 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:312537}
2538
[email protected]394816e92010-08-03 07:38:592539// Test the request-challenge-retry sequence for basic auth, over a connection
2540// that requires a restart when setting up an SSL tunnel.
ttuttle34f63b52015-03-05 04:33:012541TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
2542 HttpRequestInfo request;
2543 request.method = "GET";
bncce36dca22015-04-21 22:11:232544 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:012545 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292546 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:012547
2548 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032549 session_deps_.proxy_service =
2550 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512551 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:012552 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:062553 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:012554
2555 // Since we have proxy, should try to establish tunnel.
2556 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542557 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2558 "Host: www.example.org\r\n"
2559 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:012560 };
2561
mmenkee71e15332015-10-07 16:39:542562 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:012563 // connection.
2564 MockRead data_reads1[] = {
2565 // No credentials.
2566 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2567 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:542568 };
ttuttle34f63b52015-03-05 04:33:012569
mmenkee71e15332015-10-07 16:39:542570 // Since the first connection couldn't be reused, need to establish another
2571 // once given credentials.
2572 MockWrite data_writes2[] = {
2573 // After calling trans->RestartWithAuth(), this is the request we should
2574 // be issuing -- the final header line contains the credentials.
2575 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2576 "Host: www.example.org\r\n"
2577 "Proxy-Connection: keep-alive\r\n"
2578 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2579
2580 MockWrite("GET / HTTP/1.1\r\n"
2581 "Host: www.example.org\r\n"
2582 "Connection: keep-alive\r\n\r\n"),
2583 };
2584
2585 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:012586 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2587
2588 MockRead("HTTP/1.1 200 OK\r\n"),
2589 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2590 MockRead("Content-Length: 5\r\n\r\n"),
2591 MockRead(SYNCHRONOUS, "hello"),
2592 };
2593
2594 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2595 data_writes1, arraysize(data_writes1));
2596 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542597 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2598 data_writes2, arraysize(data_writes2));
2599 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:012600 SSLSocketDataProvider ssl(ASYNC, OK);
2601 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2602
2603 TestCompletionCallback callback1;
2604
2605 scoped_ptr<HttpTransaction> trans(
2606 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2607
2608 int rv = trans->Start(&request, callback1.callback(), log.bound());
2609 EXPECT_EQ(ERR_IO_PENDING, rv);
2610
2611 rv = callback1.WaitForResult();
2612 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462613 TestNetLogEntry::List entries;
ttuttle34f63b52015-03-05 04:33:012614 log.GetEntries(&entries);
2615 size_t pos = ExpectLogContainsSomewhere(
2616 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2617 NetLog::PHASE_NONE);
2618 ExpectLogContainsSomewhere(
2619 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2620 NetLog::PHASE_NONE);
2621
2622 const HttpResponseInfo* response = trans->GetResponseInfo();
2623 ASSERT_TRUE(response != NULL);
2624 EXPECT_FALSE(response->headers->IsKeepAlive());
2625 ASSERT_FALSE(response->headers.get() == NULL);
2626 EXPECT_EQ(407, response->headers->response_code());
2627 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2628 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2629
2630 LoadTimingInfo load_timing_info;
2631 // CONNECT requests and responses are handled at the connect job level, so
2632 // the transaction does not yet have a connection.
2633 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2634
2635 TestCompletionCallback callback2;
2636
2637 rv =
2638 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
2639 EXPECT_EQ(ERR_IO_PENDING, rv);
2640
2641 rv = callback2.WaitForResult();
2642 EXPECT_EQ(OK, rv);
2643
2644 response = trans->GetResponseInfo();
2645 ASSERT_TRUE(response != NULL);
2646
2647 EXPECT_TRUE(response->headers->IsKeepAlive());
2648 EXPECT_EQ(200, response->headers->response_code());
2649 EXPECT_EQ(5, response->headers->GetContentLength());
2650 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2651
2652 // The password prompt info should not be set.
2653 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2654
2655 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2656 TestLoadTimingNotReusedWithPac(load_timing_info,
2657 CONNECT_TIMING_HAS_SSL_TIMES);
2658
2659 trans.reset();
2660 session->CloseAllConnections();
2661}
2662
2663// Test the request-challenge-retry sequence for basic auth, over a connection
2664// that requires a restart when setting up an SSL tunnel.
2665TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:592666 HttpRequestInfo request;
2667 request.method = "GET";
bncce36dca22015-04-21 22:11:232668 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:592669 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292670 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]394816e92010-08-03 07:38:592671
[email protected]cb9bf6ca2011-01-28 13:15:272672 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032673 session_deps_.proxy_service =
2674 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512675 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072676 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:062677 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272678
[email protected]394816e92010-08-03 07:38:592679 // Since we have proxy, should try to establish tunnel.
2680 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542681 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2682 "Host: www.example.org\r\n"
2683 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:112684 };
2685
mmenkee71e15332015-10-07 16:39:542686 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:082687 // connection.
2688 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:542689 // No credentials.
2690 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2691 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2692 MockRead("Proxy-Connection: close\r\n\r\n"),
2693 };
mmenkee0b5c882015-08-26 20:29:112694
mmenkee71e15332015-10-07 16:39:542695 MockWrite data_writes2[] = {
2696 // After calling trans->RestartWithAuth(), this is the request we should
2697 // be issuing -- the final header line contains the credentials.
2698 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2699 "Host: www.example.org\r\n"
2700 "Proxy-Connection: keep-alive\r\n"
2701 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:082702
mmenkee71e15332015-10-07 16:39:542703 MockWrite("GET / HTTP/1.1\r\n"
2704 "Host: www.example.org\r\n"
2705 "Connection: keep-alive\r\n\r\n"),
2706 };
2707
2708 MockRead data_reads2[] = {
2709 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2710
2711 MockRead("HTTP/1.1 200 OK\r\n"),
2712 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2713 MockRead("Content-Length: 5\r\n\r\n"),
2714 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:592715 };
2716
2717 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2718 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:072719 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542720 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2721 data_writes2, arraysize(data_writes2));
2722 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:062723 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:072724 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:592725
[email protected]49639fa2011-12-20 23:22:412726 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:592727
[email protected]262eec82013-03-19 21:01:362728 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502729 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:502730
[email protected]49639fa2011-12-20 23:22:412731 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]394816e92010-08-03 07:38:592732 EXPECT_EQ(ERR_IO_PENDING, rv);
2733
2734 rv = callback1.WaitForResult();
2735 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462736 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:402737 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:592738 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402739 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:592740 NetLog::PHASE_NONE);
2741 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402742 entries, pos,
[email protected]394816e92010-08-03 07:38:592743 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2744 NetLog::PHASE_NONE);
2745
2746 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502747 ASSERT_TRUE(response != NULL);
ttuttle34f63b52015-03-05 04:33:012748 EXPECT_FALSE(response->headers->IsKeepAlive());
[email protected]90499482013-06-01 00:39:502749 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]394816e92010-08-03 07:38:592750 EXPECT_EQ(407, response->headers->response_code());
2751 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042752 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]394816e92010-08-03 07:38:592753
[email protected]029c83b62013-01-24 05:28:202754 LoadTimingInfo load_timing_info;
2755 // CONNECT requests and responses are handled at the connect job level, so
2756 // the transaction does not yet have a connection.
2757 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2758
[email protected]49639fa2011-12-20 23:22:412759 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:592760
[email protected]49639fa2011-12-20 23:22:412761 rv = trans->RestartWithAuth(
2762 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]394816e92010-08-03 07:38:592763 EXPECT_EQ(ERR_IO_PENDING, rv);
2764
2765 rv = callback2.WaitForResult();
2766 EXPECT_EQ(OK, rv);
2767
2768 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502769 ASSERT_TRUE(response != NULL);
[email protected]394816e92010-08-03 07:38:592770
2771 EXPECT_TRUE(response->headers->IsKeepAlive());
2772 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:502773 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:592774 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2775
2776 // The password prompt info should not be set.
2777 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502778
[email protected]029c83b62013-01-24 05:28:202779 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2780 TestLoadTimingNotReusedWithPac(load_timing_info,
2781 CONNECT_TIMING_HAS_SSL_TIMES);
2782
[email protected]0b0bf032010-09-21 18:08:502783 trans.reset();
[email protected]102e27c2011-02-23 01:01:312784 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:592785}
2786
[email protected]11203f012009-11-12 23:02:312787// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:012788// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2789TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
2790 HttpRequestInfo request;
2791 request.method = "GET";
bncce36dca22015-04-21 22:11:232792 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:012793 // Ensure that proxy authentication is attempted even
2794 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292795 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:012796
2797 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032798 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:512799 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:012800 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:062801 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:012802
2803 scoped_ptr<HttpTransaction> trans(
2804 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2805
2806 // Since we have proxy, should try to establish tunnel.
2807 MockWrite data_writes1[] = {
2808 MockWrite(
bncce36dca22015-04-21 22:11:232809 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2810 "Host: www.example.org\r\n"
ttuttle34f63b52015-03-05 04:33:012811 "Proxy-Connection: keep-alive\r\n\r\n"),
2812
2813 // After calling trans->RestartWithAuth(), this is the request we should
2814 // be issuing -- the final header line contains the credentials.
2815 MockWrite(
bncce36dca22015-04-21 22:11:232816 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2817 "Host: www.example.org\r\n"
ttuttle34f63b52015-03-05 04:33:012818 "Proxy-Connection: keep-alive\r\n"
2819 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2820 };
2821
2822 // The proxy responds to the connect with a 407, using a persistent
2823 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2824 MockRead data_reads1[] = {
2825 // No credentials.
2826 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2827 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2828 MockRead("Proxy-Connection: keep-alive\r\n"),
2829 MockRead("Content-Length: 10\r\n\r\n"),
2830 MockRead("0123456789"),
2831
2832 // Wrong credentials (wrong password).
2833 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2834 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2835 MockRead("Proxy-Connection: keep-alive\r\n"),
2836 MockRead("Content-Length: 10\r\n\r\n"),
2837 // No response body because the test stops reading here.
2838 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2839 };
2840
2841 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2842 data_writes1, arraysize(data_writes1));
2843 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2844
2845 TestCompletionCallback callback1;
2846
2847 int rv = trans->Start(&request, callback1.callback(), log.bound());
2848 EXPECT_EQ(ERR_IO_PENDING, rv);
2849
2850 rv = callback1.WaitForResult();
2851 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462852 TestNetLogEntry::List entries;
ttuttle34f63b52015-03-05 04:33:012853 log.GetEntries(&entries);
2854 size_t pos = ExpectLogContainsSomewhere(
2855 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2856 NetLog::PHASE_NONE);
2857 ExpectLogContainsSomewhere(
2858 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2859 NetLog::PHASE_NONE);
2860
2861 const HttpResponseInfo* response = trans->GetResponseInfo();
2862 ASSERT_TRUE(response);
2863 ASSERT_TRUE(response->headers);
2864 EXPECT_TRUE(response->headers->IsKeepAlive());
2865 EXPECT_EQ(407, response->headers->response_code());
2866 EXPECT_EQ(10, response->headers->GetContentLength());
2867 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2868 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2869
2870 TestCompletionCallback callback2;
2871
2872 // Wrong password (should be "bar").
2873 rv =
2874 trans->RestartWithAuth(AuthCredentials(kFoo, kBaz), callback2.callback());
2875 EXPECT_EQ(ERR_IO_PENDING, rv);
2876
2877 rv = callback2.WaitForResult();
2878 EXPECT_EQ(OK, rv);
2879
2880 response = trans->GetResponseInfo();
2881 ASSERT_TRUE(response);
2882 ASSERT_TRUE(response->headers);
2883 EXPECT_TRUE(response->headers->IsKeepAlive());
2884 EXPECT_EQ(407, response->headers->response_code());
2885 EXPECT_EQ(10, response->headers->GetContentLength());
2886 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2887 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2888
2889 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2890 // out of scope.
2891 session->CloseAllConnections();
2892}
2893
2894// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2895// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2896TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
[email protected]cb9bf6ca2011-01-28 13:15:272897 HttpRequestInfo request;
2898 request.method = "GET";
bncce36dca22015-04-21 22:11:232899 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:272900 // Ensure that proxy authentication is attempted even
2901 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292902 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]cb9bf6ca2011-01-28 13:15:272903
[email protected]2d2697f92009-02-18 21:00:322904 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032905 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:512906 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072907 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:062908 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:322909
[email protected]262eec82013-03-19 21:01:362910 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502911 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d2697f92009-02-18 21:00:322912
[email protected]2d2697f92009-02-18 21:00:322913 // Since we have proxy, should try to establish tunnel.
2914 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232915 MockWrite(
2916 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2917 "Host: www.example.org\r\n"
2918 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322919
bncce36dca22015-04-21 22:11:232920 // After calling trans->RestartWithAuth(), this is the request we should
2921 // be issuing -- the final header line contains the credentials.
2922 MockWrite(
2923 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2924 "Host: www.example.org\r\n"
2925 "Proxy-Connection: keep-alive\r\n"
2926 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322927 };
2928
2929 // The proxy responds to the connect with a 407, using a persistent
2930 // connection.
2931 MockRead data_reads1[] = {
2932 // No credentials.
2933 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2934 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2935 MockRead("Content-Length: 10\r\n\r\n"),
2936 MockRead("0123456789"),
2937
2938 // Wrong credentials (wrong password).
2939 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2940 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2941 MockRead("Content-Length: 10\r\n\r\n"),
2942 // No response body because the test stops reading here.
[email protected]8ddf8322012-02-23 18:08:062943 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:322944 };
2945
[email protected]31a2bfe2010-02-09 08:03:392946 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2947 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:072948 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:322949
[email protected]49639fa2011-12-20 23:22:412950 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322951
[email protected]49639fa2011-12-20 23:22:412952 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]1c773ea12009-04-28 19:58:422953 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322954
2955 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422956 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462957 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:402958 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:392959 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402960 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:392961 NetLog::PHASE_NONE);
2962 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402963 entries, pos,
[email protected]dbb83db2010-05-11 18:13:392964 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2965 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:322966
[email protected]1c773ea12009-04-28 19:58:422967 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:242968 ASSERT_TRUE(response);
2969 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:322970 EXPECT_TRUE(response->headers->IsKeepAlive());
2971 EXPECT_EQ(407, response->headers->response_code());
ttuttle34f63b52015-03-05 04:33:012972 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:422973 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042974 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322975
[email protected]49639fa2011-12-20 23:22:412976 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322977
2978 // Wrong password (should be "bar").
[email protected]49639fa2011-12-20 23:22:412979 rv = trans->RestartWithAuth(
2980 AuthCredentials(kFoo, kBaz), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422981 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322982
2983 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422984 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322985
2986 response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:242987 ASSERT_TRUE(response);
2988 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:322989 EXPECT_TRUE(response->headers->IsKeepAlive());
2990 EXPECT_EQ(407, response->headers->response_code());
ttuttle34f63b52015-03-05 04:33:012991 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:422992 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042993 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]e772db3f2010-07-12 18:11:132994
[email protected]e60e47a2010-07-14 03:37:182995 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2996 // out of scope.
[email protected]102e27c2011-02-23 01:01:312997 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:322998}
2999
mmenkee71e15332015-10-07 16:39:543000// Test the case a proxy closes a socket while the challenge body is being
3001// drained.
3002TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
3003 HttpRequestInfo request;
3004 request.method = "GET";
3005 request.url = GURL("https://www.example.org/");
3006 // Ensure that proxy authentication is attempted even
3007 // when the no authentication data flag is set.
3008 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
3009
3010 // Configure against proxy server "myproxy:70".
3011 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
3012 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3013
3014 scoped_ptr<HttpTransaction> trans(
3015 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3016
3017 // Since we have proxy, should try to establish tunnel.
3018 MockWrite data_writes1[] = {
3019 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3020 "Host: www.example.org\r\n"
3021 "Proxy-Connection: keep-alive\r\n\r\n"),
3022 };
3023
3024 // The proxy responds to the connect with a 407, using a persistent
3025 // connection.
3026 MockRead data_reads1[] = {
3027 // No credentials.
3028 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3029 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3030 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3031 // Server hands up in the middle of the body.
3032 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3033 };
3034
3035 MockWrite data_writes2[] = {
3036 // After calling trans->RestartWithAuth(), this is the request we should
3037 // be issuing -- the final header line contains the credentials.
3038 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3039 "Host: www.example.org\r\n"
3040 "Proxy-Connection: keep-alive\r\n"
3041 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3042
3043 MockWrite("GET / HTTP/1.1\r\n"
3044 "Host: www.example.org\r\n"
3045 "Connection: keep-alive\r\n\r\n"),
3046 };
3047
3048 MockRead data_reads2[] = {
3049 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3050
3051 MockRead("HTTP/1.1 200 OK\r\n"),
3052 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3053 MockRead("Content-Length: 5\r\n\r\n"),
3054 MockRead(SYNCHRONOUS, "hello"),
3055 };
3056
3057 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3058 data_writes1, arraysize(data_writes1));
3059 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3060 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3061 data_writes2, arraysize(data_writes2));
3062 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3063 SSLSocketDataProvider ssl(ASYNC, OK);
3064 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3065
3066 TestCompletionCallback callback;
3067
3068 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3069 EXPECT_EQ(OK, callback.GetResult(rv));
3070
3071 const HttpResponseInfo* response = trans->GetResponseInfo();
3072 ASSERT_TRUE(response);
3073 ASSERT_TRUE(response->headers);
3074 EXPECT_TRUE(response->headers->IsKeepAlive());
3075 EXPECT_EQ(407, response->headers->response_code());
3076 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3077
3078 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
3079 EXPECT_EQ(OK, callback.GetResult(rv));
3080
3081 response = trans->GetResponseInfo();
3082 ASSERT_TRUE(response);
3083 ASSERT_TRUE(response->headers);
3084 EXPECT_TRUE(response->headers->IsKeepAlive());
3085 EXPECT_EQ(200, response->headers->response_code());
3086 std::string body;
3087 EXPECT_EQ(OK, ReadTransaction(trans.get(), &body));
3088 EXPECT_EQ("hello", body);
3089}
3090
[email protected]a8e9b162009-03-12 00:06:443091// Test that we don't read the response body when we fail to establish a tunnel,
3092// even if the user cancels the proxy's auth attempt.
[email protected]23e482282013-06-14 16:08:023093TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273094 HttpRequestInfo request;
3095 request.method = "GET";
bncce36dca22015-04-21 22:11:233096 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273097 request.load_flags = 0;
3098
[email protected]a8e9b162009-03-12 00:06:443099 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033100 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]a8e9b162009-03-12 00:06:443101
mmenke6b3af6e2015-09-12 02:06:063102 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443103
[email protected]262eec82013-03-19 21:01:363104 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503105 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]a8e9b162009-03-12 00:06:443106
[email protected]a8e9b162009-03-12 00:06:443107 // Since we have proxy, should try to establish tunnel.
3108 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:233109 MockWrite(
3110 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3111 "Host: www.example.org\r\n"
3112 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443113 };
3114
3115 // The proxy responds to the connect with a 407.
3116 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243117 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3118 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3119 MockRead("Content-Length: 10\r\n\r\n"),
3120 MockRead("0123456789"), // Should not be reached.
3121 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443122 };
3123
[email protected]31a2bfe2010-02-09 08:03:393124 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3125 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:073126 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443127
[email protected]49639fa2011-12-20 23:22:413128 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443129
[email protected]49639fa2011-12-20 23:22:413130 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423131 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:443132
3133 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423134 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:443135
[email protected]1c773ea12009-04-28 19:58:423136 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243137 ASSERT_TRUE(response);
3138 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:443139 EXPECT_TRUE(response->headers->IsKeepAlive());
3140 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423141 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:443142
3143 std::string response_data;
3144 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423145 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:183146
3147 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:313148 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:443149}
3150
ttuttle7933c112015-01-06 00:55:243151// Test that we don't pass extraneous headers from the proxy's response to the
3152// caller when the proxy responds to CONNECT with 407.
3153TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
3154 HttpRequestInfo request;
3155 request.method = "GET";
bncce36dca22015-04-21 22:11:233156 request.url = GURL("https://www.example.org/");
ttuttle7933c112015-01-06 00:55:243157 request.load_flags = 0;
3158
3159 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033160 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
ttuttle7933c112015-01-06 00:55:243161
mmenke6b3af6e2015-09-12 02:06:063162 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:243163
3164 scoped_ptr<HttpTransaction> trans(
3165 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3166
3167 // Since we have proxy, should try to establish tunnel.
3168 MockWrite data_writes[] = {
3169 MockWrite(
bncce36dca22015-04-21 22:11:233170 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3171 "Host: www.example.org\r\n"
ttuttle7933c112015-01-06 00:55:243172 "Proxy-Connection: keep-alive\r\n\r\n"),
3173 };
3174
3175 // The proxy responds to the connect with a 407.
3176 MockRead data_reads[] = {
3177 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3178 MockRead("X-Foo: bar\r\n"),
3179 MockRead("Set-Cookie: foo=bar\r\n"),
3180 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3181 MockRead("Content-Length: 10\r\n\r\n"),
3182 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
3183 };
3184
3185 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
3186 arraysize(data_writes));
3187 session_deps_.socket_factory->AddSocketDataProvider(&data);
3188
3189 TestCompletionCallback callback;
3190
3191 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3192 EXPECT_EQ(ERR_IO_PENDING, rv);
3193
3194 rv = callback.WaitForResult();
3195 EXPECT_EQ(OK, rv);
3196
3197 const HttpResponseInfo* response = trans->GetResponseInfo();
3198 ASSERT_TRUE(response);
3199 ASSERT_TRUE(response->headers);
3200 EXPECT_TRUE(response->headers->IsKeepAlive());
3201 EXPECT_EQ(407, response->headers->response_code());
3202 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3203 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
3204 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
3205
3206 std::string response_data;
3207 rv = ReadTransaction(trans.get(), &response_data);
3208 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3209
3210 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3211 session->CloseAllConnections();
3212}
3213
[email protected]8fdbcd22010-05-05 02:54:523214// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
3215// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
[email protected]23e482282013-06-14 16:08:023216TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:523217 HttpRequestInfo request;
3218 request.method = "GET";
bncce36dca22015-04-21 22:11:233219 request.url = GURL("http://www.example.org/");
[email protected]8fdbcd22010-05-05 02:54:523220 request.load_flags = 0;
3221
[email protected]cb9bf6ca2011-01-28 13:15:273222 // We are using a DIRECT connection (i.e. no proxy) for this session.
mmenke6b3af6e2015-09-12 02:06:063223 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273224 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:413225 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:273226
[email protected]8fdbcd22010-05-05 02:54:523227 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233228 MockWrite(
3229 "GET / HTTP/1.1\r\n"
3230 "Host: www.example.org\r\n"
3231 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:523232 };
3233
3234 MockRead data_reads1[] = {
3235 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
3236 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3237 // Large content-length -- won't matter, as connection will be reset.
3238 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063239 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:523240 };
3241
3242 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3243 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073244 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:523245
[email protected]49639fa2011-12-20 23:22:413246 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:523247
[email protected]49639fa2011-12-20 23:22:413248 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]8fdbcd22010-05-05 02:54:523249 EXPECT_EQ(ERR_IO_PENDING, rv);
3250
3251 rv = callback.WaitForResult();
3252 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3253}
3254
[email protected]7a67a8152010-11-05 18:31:103255// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3256// through a non-authenticating proxy. The request should fail with
3257// ERR_UNEXPECTED_PROXY_AUTH.
3258// Note that it is impossible to detect if an HTTP server returns a 407 through
3259// a non-authenticating proxy - there is nothing to indicate whether the
3260// response came from the proxy or the server, so it is treated as if the proxy
3261// issued the challenge.
[email protected]23e482282013-06-14 16:08:023262TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:233263 HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:273264 HttpRequestInfo request;
3265 request.method = "GET";
bncce36dca22015-04-21 22:11:233266 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273267
rdsmith82957ad2015-09-16 19:42:033268 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:513269 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073270 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:063271 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:103272
[email protected]7a67a8152010-11-05 18:31:103273 // Since we have proxy, should try to establish tunnel.
3274 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233275 MockWrite(
3276 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3277 "Host: www.example.org\r\n"
3278 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103279
bncce36dca22015-04-21 22:11:233280 MockWrite(
3281 "GET / HTTP/1.1\r\n"
3282 "Host: www.example.org\r\n"
3283 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103284 };
3285
3286 MockRead data_reads1[] = {
3287 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3288
3289 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3290 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3291 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:063292 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:103293 };
3294
3295 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3296 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073297 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:063298 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073299 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:103300
[email protected]49639fa2011-12-20 23:22:413301 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:103302
[email protected]262eec82013-03-19 21:01:363303 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503304 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a67a8152010-11-05 18:31:103305
[email protected]49639fa2011-12-20 23:22:413306 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7a67a8152010-11-05 18:31:103307 EXPECT_EQ(ERR_IO_PENDING, rv);
3308
3309 rv = callback1.WaitForResult();
3310 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
mmenke43758e62015-05-04 21:09:463311 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403312 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:103313 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403314 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:103315 NetLog::PHASE_NONE);
3316 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403317 entries, pos,
[email protected]7a67a8152010-11-05 18:31:103318 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3319 NetLog::PHASE_NONE);
3320}
[email protected]2df19bb2010-08-25 20:13:463321
mmenke2a1781d2015-10-07 19:25:333322// Test a proxy auth scheme that allows default credentials and a proxy server
3323// that uses non-persistent connections.
3324TEST_P(HttpNetworkTransactionTest,
3325 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
3326 HttpRequestInfo request;
3327 request.method = "GET";
3328 request.url = GURL("https://www.example.org/");
3329
3330 // Configure against proxy server "myproxy:70".
3331 session_deps_.proxy_service =
3332 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3333
3334 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3335 new HttpAuthHandlerMock::Factory());
3336 auth_handler_factory->set_do_init_from_challenge(true);
3337 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3338 mock_handler->set_allows_default_credentials(true);
3339 auth_handler_factory->AddMockHandler(mock_handler.release(),
3340 HttpAuth::AUTH_PROXY);
3341 session_deps_.http_auth_handler_factory = auth_handler_factory.Pass();
3342
3343 // Add NetLog just so can verify load timing information gets a NetLog ID.
3344 NetLog net_log;
3345 session_deps_.net_log = &net_log;
3346 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3347
3348 // Since we have proxy, should try to establish tunnel.
3349 MockWrite data_writes1[] = {
3350 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3351 "Host: www.example.org\r\n"
3352 "Proxy-Connection: keep-alive\r\n\r\n"),
3353 };
3354
3355 // The proxy responds to the connect with a 407, using a non-persistent
3356 // connection.
3357 MockRead data_reads1[] = {
3358 // No credentials.
3359 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3360 MockRead("Proxy-Authenticate: Mock\r\n"),
3361 MockRead("Proxy-Connection: close\r\n\r\n"),
3362 };
3363
3364 // Since the first connection couldn't be reused, need to establish another
3365 // once given credentials.
3366 MockWrite data_writes2[] = {
3367 // After calling trans->RestartWithAuth(), this is the request we should
3368 // be issuing -- the final header line contains the credentials.
3369 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3370 "Host: www.example.org\r\n"
3371 "Proxy-Connection: keep-alive\r\n"
3372 "Proxy-Authorization: auth_token\r\n\r\n"),
3373
3374 MockWrite("GET / HTTP/1.1\r\n"
3375 "Host: www.example.org\r\n"
3376 "Connection: keep-alive\r\n\r\n"),
3377 };
3378
3379 MockRead data_reads2[] = {
3380 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3381
3382 MockRead("HTTP/1.1 200 OK\r\n"),
3383 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3384 MockRead("Content-Length: 5\r\n\r\n"),
3385 MockRead(SYNCHRONOUS, "hello"),
3386 };
3387
3388 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3389 data_writes1, arraysize(data_writes1));
3390 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3391 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3392 data_writes2, arraysize(data_writes2));
3393 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3394 SSLSocketDataProvider ssl(ASYNC, OK);
3395 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3396
3397 scoped_ptr<HttpTransaction> trans(
3398 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3399
3400 TestCompletionCallback callback;
3401 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3402 EXPECT_EQ(OK, callback.GetResult(rv));
3403
3404 const HttpResponseInfo* response = trans->GetResponseInfo();
3405 ASSERT_TRUE(response);
3406 ASSERT_TRUE(response->headers);
3407 EXPECT_FALSE(response->headers->IsKeepAlive());
3408 EXPECT_EQ(407, response->headers->response_code());
3409 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3410 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3411 EXPECT_FALSE(response->auth_challenge.get());
3412
3413 LoadTimingInfo load_timing_info;
3414 // CONNECT requests and responses are handled at the connect job level, so
3415 // the transaction does not yet have a connection.
3416 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3417
3418 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3419 EXPECT_EQ(OK, callback.GetResult(rv));
3420 response = trans->GetResponseInfo();
3421 ASSERT_TRUE(response);
3422 ASSERT_TRUE(response->headers);
3423 EXPECT_TRUE(response->headers->IsKeepAlive());
3424 EXPECT_EQ(200, response->headers->response_code());
3425 EXPECT_EQ(5, response->headers->GetContentLength());
3426 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3427
3428 // The password prompt info should not be set.
3429 EXPECT_FALSE(response->auth_challenge);
3430
3431 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3432 TestLoadTimingNotReusedWithPac(load_timing_info,
3433 CONNECT_TIMING_HAS_SSL_TIMES);
3434
3435 trans.reset();
3436 session->CloseAllConnections();
3437}
3438
3439// Test a proxy auth scheme that allows default credentials and a proxy server
3440// that hangs up when credentials are initially sent.
3441TEST_P(HttpNetworkTransactionTest,
3442 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
3443 HttpRequestInfo request;
3444 request.method = "GET";
3445 request.url = GURL("https://www.example.org/");
3446
3447 // Configure against proxy server "myproxy:70".
3448 session_deps_.proxy_service =
3449 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3450
3451 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3452 new HttpAuthHandlerMock::Factory());
3453 auth_handler_factory->set_do_init_from_challenge(true);
3454 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3455 mock_handler->set_allows_default_credentials(true);
3456 auth_handler_factory->AddMockHandler(mock_handler.release(),
3457 HttpAuth::AUTH_PROXY);
3458 session_deps_.http_auth_handler_factory = auth_handler_factory.Pass();
3459
3460 // Add NetLog just so can verify load timing information gets a NetLog ID.
3461 NetLog net_log;
3462 session_deps_.net_log = &net_log;
3463 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3464
3465 // Should try to establish tunnel.
3466 MockWrite data_writes1[] = {
3467 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3468 "Host: www.example.org\r\n"
3469 "Proxy-Connection: keep-alive\r\n\r\n"),
3470
3471 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3472 "Host: www.example.org\r\n"
3473 "Proxy-Connection: keep-alive\r\n"
3474 "Proxy-Authorization: auth_token\r\n\r\n"),
3475 };
3476
3477 // The proxy responds to the connect with a 407, using a non-persistent
3478 // connection.
3479 MockRead data_reads1[] = {
3480 // No credentials.
3481 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3482 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3483 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3484 };
3485
3486 // Since the first connection was closed, need to establish another once given
3487 // credentials.
3488 MockWrite data_writes2[] = {
3489 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3490 "Host: www.example.org\r\n"
3491 "Proxy-Connection: keep-alive\r\n"
3492 "Proxy-Authorization: auth_token\r\n\r\n"),
3493
3494 MockWrite("GET / HTTP/1.1\r\n"
3495 "Host: www.example.org\r\n"
3496 "Connection: keep-alive\r\n\r\n"),
3497 };
3498
3499 MockRead data_reads2[] = {
3500 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3501
3502 MockRead("HTTP/1.1 200 OK\r\n"),
3503 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3504 MockRead("Content-Length: 5\r\n\r\n"),
3505 MockRead(SYNCHRONOUS, "hello"),
3506 };
3507
3508 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3509 data_writes1, arraysize(data_writes1));
3510 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3511 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3512 data_writes2, arraysize(data_writes2));
3513 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3514 SSLSocketDataProvider ssl(ASYNC, OK);
3515 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3516
3517 scoped_ptr<HttpTransaction> trans(
3518 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3519
3520 TestCompletionCallback callback;
3521 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3522 EXPECT_EQ(OK, callback.GetResult(rv));
3523
3524 const HttpResponseInfo* response = trans->GetResponseInfo();
3525 ASSERT_TRUE(response);
3526 ASSERT_TRUE(response->headers);
3527 EXPECT_TRUE(response->headers->IsKeepAlive());
3528 EXPECT_EQ(407, response->headers->response_code());
3529 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3530 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3531 EXPECT_FALSE(response->auth_challenge);
3532
3533 LoadTimingInfo load_timing_info;
3534 // CONNECT requests and responses are handled at the connect job level, so
3535 // the transaction does not yet have a connection.
3536 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3537
3538 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3539 EXPECT_EQ(OK, callback.GetResult(rv));
3540
3541 response = trans->GetResponseInfo();
3542 ASSERT_TRUE(response);
3543 ASSERT_TRUE(response->headers);
3544 EXPECT_TRUE(response->headers->IsKeepAlive());
3545 EXPECT_EQ(200, response->headers->response_code());
3546 EXPECT_EQ(5, response->headers->GetContentLength());
3547 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3548
3549 // The password prompt info should not be set.
3550 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3551
3552 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3553 TestLoadTimingNotReusedWithPac(load_timing_info,
3554 CONNECT_TIMING_HAS_SSL_TIMES);
3555
3556 trans.reset();
3557 session->CloseAllConnections();
3558}
3559
3560// Test a proxy auth scheme that allows default credentials and a proxy server
3561// that hangs up when credentials are initially sent, and hangs up again when
3562// they are retried.
3563TEST_P(HttpNetworkTransactionTest,
3564 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
3565 HttpRequestInfo request;
3566 request.method = "GET";
3567 request.url = GURL("https://www.example.org/");
3568
3569 // Configure against proxy server "myproxy:70".
3570 session_deps_.proxy_service =
3571 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3572
3573 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3574 new HttpAuthHandlerMock::Factory());
3575 auth_handler_factory->set_do_init_from_challenge(true);
3576 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3577 mock_handler->set_allows_default_credentials(true);
3578 auth_handler_factory->AddMockHandler(mock_handler.release(),
3579 HttpAuth::AUTH_PROXY);
3580 session_deps_.http_auth_handler_factory = auth_handler_factory.Pass();
3581
3582 // Add NetLog just so can verify load timing information gets a NetLog ID.
3583 NetLog net_log;
3584 session_deps_.net_log = &net_log;
3585 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3586
3587 // Should try to establish tunnel.
3588 MockWrite data_writes1[] = {
3589 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3590 "Host: www.example.org\r\n"
3591 "Proxy-Connection: keep-alive\r\n\r\n"),
3592
3593 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3594 "Host: www.example.org\r\n"
3595 "Proxy-Connection: keep-alive\r\n"
3596 "Proxy-Authorization: auth_token\r\n\r\n"),
3597 };
3598
3599 // The proxy responds to the connect with a 407, and then hangs up after the
3600 // second request is sent.
3601 MockRead data_reads1[] = {
3602 // No credentials.
3603 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3604 MockRead("Content-Length: 0\r\n"),
3605 MockRead("Proxy-Connection: keep-alive\r\n"),
3606 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3607 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3608 };
3609
3610 // HttpNetworkTransaction sees a reused connection that was closed with
3611 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
3612 // request.
3613 MockWrite data_writes2[] = {
3614 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3615 "Host: www.example.org\r\n"
3616 "Proxy-Connection: keep-alive\r\n\r\n"),
3617 };
3618
3619 // The proxy, having had more than enough of us, just hangs up.
3620 MockRead data_reads2[] = {
3621 // No credentials.
3622 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3623 };
3624
3625 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3626 data_writes1, arraysize(data_writes1));
3627 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3628 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3629 data_writes2, arraysize(data_writes2));
3630 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3631
3632 scoped_ptr<HttpTransaction> trans(
3633 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3634
3635 TestCompletionCallback callback;
3636 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3637 EXPECT_EQ(OK, callback.GetResult(rv));
3638
3639 const HttpResponseInfo* response = trans->GetResponseInfo();
3640 ASSERT_TRUE(response);
3641 ASSERT_TRUE(response->headers);
3642 EXPECT_TRUE(response->headers->IsKeepAlive());
3643 EXPECT_EQ(407, response->headers->response_code());
3644 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3645 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3646 EXPECT_FALSE(response->auth_challenge);
3647
3648 LoadTimingInfo load_timing_info;
3649 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3650
3651 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3652 EXPECT_EQ(ERR_EMPTY_RESPONSE, callback.GetResult(rv));
3653
3654 trans.reset();
3655 session->CloseAllConnections();
3656}
3657
3658// Test a proxy auth scheme that allows default credentials and a proxy server
3659// that hangs up when credentials are initially sent, and sends a challenge
3660// again they are retried.
3661TEST_P(HttpNetworkTransactionTest,
3662 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
3663 HttpRequestInfo request;
3664 request.method = "GET";
3665 request.url = GURL("https://www.example.org/");
3666
3667 // Configure against proxy server "myproxy:70".
3668 session_deps_.proxy_service =
3669 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3670
3671 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3672 new HttpAuthHandlerMock::Factory());
3673 auth_handler_factory->set_do_init_from_challenge(true);
3674 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3675 mock_handler->set_allows_default_credentials(true);
3676 auth_handler_factory->AddMockHandler(mock_handler.release(),
3677 HttpAuth::AUTH_PROXY);
3678 // Add another handler for the second challenge. It supports default
3679 // credentials, but they shouldn't be used, since they were already tried.
3680 mock_handler.reset(new HttpAuthHandlerMock());
3681 mock_handler->set_allows_default_credentials(true);
3682 auth_handler_factory->AddMockHandler(mock_handler.release(),
3683 HttpAuth::AUTH_PROXY);
3684 session_deps_.http_auth_handler_factory = auth_handler_factory.Pass();
3685
3686 // Add NetLog just so can verify load timing information gets a NetLog ID.
3687 NetLog net_log;
3688 session_deps_.net_log = &net_log;
3689 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3690
3691 // Should try to establish tunnel.
3692 MockWrite data_writes1[] = {
3693 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3694 "Host: www.example.org\r\n"
3695 "Proxy-Connection: keep-alive\r\n\r\n"),
3696 };
3697
3698 // The proxy responds to the connect with a 407, using a non-persistent
3699 // connection.
3700 MockRead data_reads1[] = {
3701 // No credentials.
3702 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3703 MockRead("Proxy-Authenticate: Mock\r\n"),
3704 MockRead("Proxy-Connection: close\r\n\r\n"),
3705 };
3706
3707 // Since the first connection was closed, need to establish another once given
3708 // credentials.
3709 MockWrite data_writes2[] = {
3710 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3711 "Host: www.example.org\r\n"
3712 "Proxy-Connection: keep-alive\r\n"
3713 "Proxy-Authorization: auth_token\r\n\r\n"),
3714 };
3715
3716 MockRead data_reads2[] = {
3717 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3718 MockRead("Proxy-Authenticate: Mock\r\n"),
3719 MockRead("Proxy-Connection: close\r\n\r\n"),
3720 };
3721
3722 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3723 data_writes1, arraysize(data_writes1));
3724 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3725 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3726 data_writes2, arraysize(data_writes2));
3727 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3728 SSLSocketDataProvider ssl(ASYNC, OK);
3729 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3730
3731 scoped_ptr<HttpTransaction> trans(
3732 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3733
3734 TestCompletionCallback callback;
3735 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3736 EXPECT_EQ(OK, callback.GetResult(rv));
3737
3738 const HttpResponseInfo* response = trans->GetResponseInfo();
3739 ASSERT_TRUE(response);
3740 ASSERT_TRUE(response->headers);
3741 EXPECT_EQ(407, response->headers->response_code());
3742 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3743 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3744 EXPECT_FALSE(response->auth_challenge);
3745
3746 LoadTimingInfo load_timing_info;
3747 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3748
3749 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3750 EXPECT_EQ(OK, callback.GetResult(rv));
3751 response = trans->GetResponseInfo();
3752 ASSERT_TRUE(response);
3753 ASSERT_TRUE(response->headers);
3754 EXPECT_EQ(407, response->headers->response_code());
3755 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3756 EXPECT_TRUE(response->auth_challenge);
3757
3758 trans.reset();
3759 session->CloseAllConnections();
3760}
3761
[email protected]029c83b62013-01-24 05:28:203762// Test the load timing for HTTPS requests with an HTTP proxy.
[email protected]23e482282013-06-14 16:08:023763TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:203764 HttpRequestInfo request1;
3765 request1.method = "GET";
bncce36dca22015-04-21 22:11:233766 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:203767
3768 HttpRequestInfo request2;
3769 request2.method = "GET";
bncce36dca22015-04-21 22:11:233770 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:203771
3772 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033773 session_deps_.proxy_service = ProxyService::CreateFixed("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:513774 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073775 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:063776 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:203777
3778 // Since we have proxy, should try to establish tunnel.
3779 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233780 MockWrite(
3781 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3782 "Host: www.example.org\r\n"
3783 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203784
bncce36dca22015-04-21 22:11:233785 MockWrite(
3786 "GET /1 HTTP/1.1\r\n"
3787 "Host: www.example.org\r\n"
3788 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203789
bncce36dca22015-04-21 22:11:233790 MockWrite(
3791 "GET /2 HTTP/1.1\r\n"
3792 "Host: www.example.org\r\n"
3793 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203794 };
3795
3796 // The proxy responds to the connect with a 407, using a persistent
3797 // connection.
3798 MockRead data_reads1[] = {
3799 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3800
3801 MockRead("HTTP/1.1 200 OK\r\n"),
3802 MockRead("Content-Length: 1\r\n\r\n"),
3803 MockRead(SYNCHRONOUS, "1"),
3804
3805 MockRead("HTTP/1.1 200 OK\r\n"),
3806 MockRead("Content-Length: 2\r\n\r\n"),
3807 MockRead(SYNCHRONOUS, "22"),
3808 };
3809
3810 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3811 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073812 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:203813 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073814 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:203815
3816 TestCompletionCallback callback1;
[email protected]262eec82013-03-19 21:01:363817 scoped_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:503818 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:203819
3820 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3821 EXPECT_EQ(ERR_IO_PENDING, rv);
3822
3823 rv = callback1.WaitForResult();
3824 EXPECT_EQ(OK, rv);
3825
3826 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3827 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:503828 ASSERT_TRUE(response1->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:203829 EXPECT_EQ(1, response1->headers->GetContentLength());
3830
3831 LoadTimingInfo load_timing_info1;
3832 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3833 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
3834
3835 trans1.reset();
3836
3837 TestCompletionCallback callback2;
[email protected]262eec82013-03-19 21:01:363838 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:503839 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:203840
3841 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3842 EXPECT_EQ(ERR_IO_PENDING, rv);
3843
3844 rv = callback2.WaitForResult();
3845 EXPECT_EQ(OK, rv);
3846
3847 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3848 ASSERT_TRUE(response2 != NULL);
[email protected]90499482013-06-01 00:39:503849 ASSERT_TRUE(response2->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:203850 EXPECT_EQ(2, response2->headers->GetContentLength());
3851
3852 LoadTimingInfo load_timing_info2;
3853 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3854 TestLoadTimingReused(load_timing_info2);
3855
3856 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3857
3858 trans2.reset();
3859 session->CloseAllConnections();
3860}
3861
3862// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
[email protected]23e482282013-06-14 16:08:023863TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:203864 HttpRequestInfo request1;
3865 request1.method = "GET";
bncce36dca22015-04-21 22:11:233866 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:203867
3868 HttpRequestInfo request2;
3869 request2.method = "GET";
bncce36dca22015-04-21 22:11:233870 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:203871
3872 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033873 session_deps_.proxy_service =
3874 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:513875 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073876 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:063877 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:203878
3879 // Since we have proxy, should try to establish tunnel.
3880 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233881 MockWrite(
3882 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3883 "Host: www.example.org\r\n"
3884 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203885
bncce36dca22015-04-21 22:11:233886 MockWrite(
3887 "GET /1 HTTP/1.1\r\n"
3888 "Host: www.example.org\r\n"
3889 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203890
bncce36dca22015-04-21 22:11:233891 MockWrite(
3892 "GET /2 HTTP/1.1\r\n"
3893 "Host: www.example.org\r\n"
3894 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203895 };
3896
3897 // The proxy responds to the connect with a 407, using a persistent
3898 // connection.
3899 MockRead data_reads1[] = {
3900 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3901
3902 MockRead("HTTP/1.1 200 OK\r\n"),
3903 MockRead("Content-Length: 1\r\n\r\n"),
3904 MockRead(SYNCHRONOUS, "1"),
3905
3906 MockRead("HTTP/1.1 200 OK\r\n"),
3907 MockRead("Content-Length: 2\r\n\r\n"),
3908 MockRead(SYNCHRONOUS, "22"),
3909 };
3910
3911 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3912 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073913 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:203914 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073915 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:203916
3917 TestCompletionCallback callback1;
[email protected]262eec82013-03-19 21:01:363918 scoped_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:503919 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:203920
3921 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
3922 EXPECT_EQ(ERR_IO_PENDING, rv);
3923
3924 rv = callback1.WaitForResult();
3925 EXPECT_EQ(OK, rv);
3926
3927 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
3928 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:503929 ASSERT_TRUE(response1->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:203930 EXPECT_EQ(1, response1->headers->GetContentLength());
3931
3932 LoadTimingInfo load_timing_info1;
3933 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
3934 TestLoadTimingNotReusedWithPac(load_timing_info1,
3935 CONNECT_TIMING_HAS_SSL_TIMES);
3936
3937 trans1.reset();
3938
3939 TestCompletionCallback callback2;
[email protected]262eec82013-03-19 21:01:363940 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:503941 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:203942
3943 rv = trans2->Start(&request2, callback2.callback(), log.bound());
3944 EXPECT_EQ(ERR_IO_PENDING, rv);
3945
3946 rv = callback2.WaitForResult();
3947 EXPECT_EQ(OK, rv);
3948
3949 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
3950 ASSERT_TRUE(response2 != NULL);
[email protected]90499482013-06-01 00:39:503951 ASSERT_TRUE(response2->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:203952 EXPECT_EQ(2, response2->headers->GetContentLength());
3953
3954 LoadTimingInfo load_timing_info2;
3955 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3956 TestLoadTimingReusedWithPac(load_timing_info2);
3957
3958 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3959
3960 trans2.reset();
3961 session->CloseAllConnections();
3962}
3963
[email protected]2df19bb2010-08-25 20:13:463964// Test a simple get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:023965TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:273966 HttpRequestInfo request;
3967 request.method = "GET";
bncce36dca22015-04-21 22:11:233968 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273969
[email protected]2df19bb2010-08-25 20:13:463970 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:033971 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:513972 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073973 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:063974 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:463975
[email protected]2df19bb2010-08-25 20:13:463976 // Since we have proxy, should use full url
3977 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233978 MockWrite(
3979 "GET http://www.example.org/ HTTP/1.1\r\n"
3980 "Host: www.example.org\r\n"
3981 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:463982 };
3983
3984 MockRead data_reads1[] = {
3985 MockRead("HTTP/1.1 200 OK\r\n"),
3986 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3987 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063988 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:463989 };
3990
3991 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3992 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073993 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:063994 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073995 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:463996
[email protected]49639fa2011-12-20 23:22:413997 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:463998
[email protected]262eec82013-03-19 21:01:363999 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504000 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504001
[email protected]49639fa2011-12-20 23:22:414002 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:464003 EXPECT_EQ(ERR_IO_PENDING, rv);
4004
4005 rv = callback1.WaitForResult();
4006 EXPECT_EQ(OK, rv);
4007
[email protected]58e32bb2013-01-21 18:23:254008 LoadTimingInfo load_timing_info;
4009 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4010 TestLoadTimingNotReused(load_timing_info,
4011 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4012
[email protected]2df19bb2010-08-25 20:13:464013 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504014 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464015
4016 EXPECT_TRUE(response->headers->IsKeepAlive());
4017 EXPECT_EQ(200, response->headers->response_code());
4018 EXPECT_EQ(100, response->headers->GetContentLength());
4019 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4020
4021 // The password prompt info should not be set.
4022 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4023}
4024
[email protected]7642b5ae2010-09-01 20:55:174025// Test a SPDY get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024026TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:274027 HttpRequestInfo request;
4028 request.method = "GET";
bncce36dca22015-04-21 22:11:234029 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274030 request.load_flags = 0;
4031
[email protected]7642b5ae2010-09-01 20:55:174032 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034033 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514034 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074035 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:064036 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:174037
bncce36dca22015-04-21 22:11:234038 // fetch http://www.example.org/ via SPDY
[email protected]cdf8f7e72013-05-23 10:56:464039 scoped_ptr<SpdyFrame> req(
4040 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rch8e6c6c42015-05-01 14:05:134041 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]7642b5ae2010-09-01 20:55:174042
[email protected]23e482282013-06-14 16:08:024043 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4044 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:174045 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134046 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:174047 };
4048
rch8e6c6c42015-05-01 14:05:134049 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4050 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074051 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:174052
[email protected]8ddf8322012-02-23 18:08:064053 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:024054 ssl.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:074055 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:174056
[email protected]49639fa2011-12-20 23:22:414057 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:174058
[email protected]262eec82013-03-19 21:01:364059 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504060 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504061
[email protected]49639fa2011-12-20 23:22:414062 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7642b5ae2010-09-01 20:55:174063 EXPECT_EQ(ERR_IO_PENDING, rv);
4064
4065 rv = callback1.WaitForResult();
4066 EXPECT_EQ(OK, rv);
4067
[email protected]58e32bb2013-01-21 18:23:254068 LoadTimingInfo load_timing_info;
4069 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4070 TestLoadTimingNotReused(load_timing_info,
4071 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4072
[email protected]7642b5ae2010-09-01 20:55:174073 const HttpResponseInfo* response = trans->GetResponseInfo();
4074 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504075 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]7642b5ae2010-09-01 20:55:174076 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4077
4078 std::string response_data;
4079 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]448d4ca52012-03-04 04:12:234080 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:174081}
4082
[email protected]1c173852014-06-19 12:51:504083// Verifies that a session which races and wins against the owning transaction
4084// (completing prior to host resolution), doesn't fail the transaction.
4085// Regression test for crbug.com/334413.
4086TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
4087 HttpRequestInfo request;
4088 request.method = "GET";
bncce36dca22015-04-21 22:11:234089 request.url = GURL("http://www.example.org/");
[email protected]1c173852014-06-19 12:51:504090 request.load_flags = 0;
4091
4092 // Configure SPDY proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034093 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514094 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:504095 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:064096 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:504097
bncce36dca22015-04-21 22:11:234098 // Fetch http://www.example.org/ through the SPDY proxy.
[email protected]1c173852014-06-19 12:51:504099 scoped_ptr<SpdyFrame> req(
4100 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rch8e6c6c42015-05-01 14:05:134101 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]1c173852014-06-19 12:51:504102
4103 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4104 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
4105 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134106 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:504107 };
4108
rch8e6c6c42015-05-01 14:05:134109 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4110 arraysize(spdy_writes));
[email protected]1c173852014-06-19 12:51:504111 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4112
4113 SSLSocketDataProvider ssl(ASYNC, OK);
4114 ssl.SetNextProto(GetParam());
4115 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4116
4117 TestCompletionCallback callback1;
4118
4119 scoped_ptr<HttpTransaction> trans(
4120 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4121
4122 // Stall the hostname resolution begun by the transaction.
4123 session_deps_.host_resolver->set_synchronous_mode(false);
4124 session_deps_.host_resolver->set_ondemand_mode(true);
4125
4126 int rv = trans->Start(&request, callback1.callback(), log.bound());
4127 EXPECT_EQ(ERR_IO_PENDING, rv);
4128
4129 // Race a session to the proxy, which completes first.
4130 session_deps_.host_resolver->set_ondemand_mode(false);
4131 SpdySessionKey key(
4132 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
4133 base::WeakPtr<SpdySession> spdy_session =
mmenke6b3af6e2015-09-12 02:06:064134 CreateSecureSpdySession(session, key, log.bound());
[email protected]1c173852014-06-19 12:51:504135
4136 // Unstall the resolution begun by the transaction.
4137 session_deps_.host_resolver->set_ondemand_mode(true);
4138 session_deps_.host_resolver->ResolveAllPending();
4139
4140 EXPECT_FALSE(callback1.have_result());
4141 rv = callback1.WaitForResult();
4142 EXPECT_EQ(OK, rv);
4143
4144 const HttpResponseInfo* response = trans->GetResponseInfo();
4145 ASSERT_TRUE(response != NULL);
4146 ASSERT_TRUE(response->headers.get() != NULL);
4147 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4148
4149 std::string response_data;
4150 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4151 EXPECT_EQ(kUploadData, response_data);
4152}
4153
[email protected]dc7bd1c52010-11-12 00:01:134154// Test a SPDY get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024155TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:274156 HttpRequestInfo request;
4157 request.method = "GET";
bncce36dca22015-04-21 22:11:234158 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274159 request.load_flags = 0;
4160
[email protected]79cb5c12011-09-12 13:12:044161 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034162 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:514163 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074164 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:064165 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:134166
[email protected]dc7bd1c52010-11-12 00:01:134167 // The first request will be a bare GET, the second request will be a
4168 // GET with a Proxy-Authorization header.
[email protected]ff98d7f02012-03-22 21:44:194169 scoped_ptr<SpdyFrame> req_get(
[email protected]cdf8f7e72013-05-23 10:56:464170 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
[email protected]dc7bd1c52010-11-12 00:01:134171 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464172 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:134173 };
[email protected]ff98d7f02012-03-22 21:44:194174 scoped_ptr<SpdyFrame> req_get_authorization(
[email protected]cdf8f7e72013-05-23 10:56:464175 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4176 arraysize(kExtraAuthorizationHeaders) / 2,
4177 false,
4178 3,
4179 LOWEST,
4180 false));
[email protected]dc7bd1c52010-11-12 00:01:134181 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134182 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:134183 };
4184
4185 // The first response is a 407 proxy authentication challenge, and the second
4186 // response will be a 200 response since the second request includes a valid
4187 // Authorization header.
4188 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464189 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:134190 };
[email protected]ff98d7f02012-03-22 21:44:194191 scoped_ptr<SpdyFrame> resp_authentication(
[email protected]23e482282013-06-14 16:08:024192 spdy_util_.ConstructSpdySynReplyError(
[email protected]dc7bd1c52010-11-12 00:01:134193 "407 Proxy Authentication Required",
4194 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
4195 1));
[email protected]ff98d7f02012-03-22 21:44:194196 scoped_ptr<SpdyFrame> body_authentication(
[email protected]23e482282013-06-14 16:08:024197 spdy_util_.ConstructSpdyBodyFrame(1, true));
4198 scoped_ptr<SpdyFrame> resp_data(
4199 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4200 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:134201 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134202 CreateMockRead(*resp_authentication, 1),
4203 CreateMockRead(*body_authentication, 2),
4204 CreateMockRead(*resp_data, 4),
4205 CreateMockRead(*body_data, 5),
4206 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:134207 };
4208
rch8e6c6c42015-05-01 14:05:134209 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4210 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074211 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:134212
[email protected]8ddf8322012-02-23 18:08:064213 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:024214 ssl.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:074215 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:134216
[email protected]49639fa2011-12-20 23:22:414217 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:134218
[email protected]262eec82013-03-19 21:01:364219 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504220 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]dc7bd1c52010-11-12 00:01:134221
[email protected]49639fa2011-12-20 23:22:414222 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]dc7bd1c52010-11-12 00:01:134223 EXPECT_EQ(ERR_IO_PENDING, rv);
4224
4225 rv = callback1.WaitForResult();
4226 EXPECT_EQ(OK, rv);
4227
4228 const HttpResponseInfo* const response = trans->GetResponseInfo();
4229
4230 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504231 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]dc7bd1c52010-11-12 00:01:134232 EXPECT_EQ(407, response->headers->response_code());
4233 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:044234 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]dc7bd1c52010-11-12 00:01:134235
[email protected]49639fa2011-12-20 23:22:414236 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:134237
[email protected]49639fa2011-12-20 23:22:414238 rv = trans->RestartWithAuth(
4239 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]dc7bd1c52010-11-12 00:01:134240 EXPECT_EQ(ERR_IO_PENDING, rv);
4241
4242 rv = callback2.WaitForResult();
4243 EXPECT_EQ(OK, rv);
4244
4245 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4246
4247 ASSERT_TRUE(response_restart != NULL);
[email protected]90499482013-06-01 00:39:504248 ASSERT_TRUE(response_restart->headers.get() != NULL);
[email protected]dc7bd1c52010-11-12 00:01:134249 EXPECT_EQ(200, response_restart->headers->response_code());
4250 // The password prompt info should not be set.
4251 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4252}
4253
[email protected]d9da5fe2010-10-13 22:37:164254// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
[email protected]23e482282013-06-14 16:08:024255TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:274256 HttpRequestInfo request;
4257 request.method = "GET";
bncce36dca22015-04-21 22:11:234258 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274259 request.load_flags = 0;
4260
[email protected]d9da5fe2010-10-13 22:37:164261 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034262 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514263 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074264 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:064265 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164266
[email protected]262eec82013-03-19 21:01:364267 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504268 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164269
bncce36dca22015-04-21 22:11:234270 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344271 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234272 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
4273 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:164274
bncce36dca22015-04-21 22:11:234275 const char get[] =
4276 "GET / HTTP/1.1\r\n"
4277 "Host: www.example.org\r\n"
4278 "Connection: keep-alive\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:194279 scoped_ptr<SpdyFrame> wrapped_get(
[email protected]23e482282013-06-14 16:08:024280 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
4281 scoped_ptr<SpdyFrame> conn_resp(
4282 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:164283 const char resp[] = "HTTP/1.1 200 OK\r\n"
4284 "Content-Length: 10\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:194285 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:024286 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
[email protected]ff98d7f02012-03-22 21:44:194287 scoped_ptr<SpdyFrame> wrapped_body(
[email protected]23e482282013-06-14 16:08:024288 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
[email protected]ff98d7f02012-03-22 21:44:194289 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204290 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
[email protected]8d2f7012012-02-16 00:08:044291
4292 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134293 CreateMockWrite(*connect, 0),
4294 CreateMockWrite(*wrapped_get, 2),
4295 CreateMockWrite(*window_update, 6),
[email protected]8d2f7012012-02-16 00:08:044296 };
4297
[email protected]d9da5fe2010-10-13 22:37:164298 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134299 CreateMockRead(*conn_resp, 1, ASYNC),
4300 CreateMockRead(*wrapped_get_resp, 3, ASYNC),
4301 CreateMockRead(*wrapped_body, 4, ASYNC),
4302 CreateMockRead(*wrapped_body, 5, ASYNC),
4303 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:164304 };
4305
rch8e6c6c42015-05-01 14:05:134306 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4307 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074308 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164309
[email protected]8ddf8322012-02-23 18:08:064310 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:024311 ssl.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:074312 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064313 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074314 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164315
[email protected]49639fa2011-12-20 23:22:414316 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164317
[email protected]49639fa2011-12-20 23:22:414318 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164319 EXPECT_EQ(ERR_IO_PENDING, rv);
4320
4321 rv = callback1.WaitForResult();
rch8e6c6c42015-05-01 14:05:134322 ASSERT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:164323
[email protected]58e32bb2013-01-21 18:23:254324 LoadTimingInfo load_timing_info;
4325 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4326 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4327
[email protected]d9da5fe2010-10-13 22:37:164328 const HttpResponseInfo* response = trans->GetResponseInfo();
4329 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504330 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]d9da5fe2010-10-13 22:37:164331 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4332
4333 std::string response_data;
4334 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4335 EXPECT_EQ("1234567890", response_data);
4336}
4337
4338// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
[email protected]23e482282013-06-14 16:08:024339TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:274340 HttpRequestInfo request;
4341 request.method = "GET";
bncce36dca22015-04-21 22:11:234342 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274343 request.load_flags = 0;
4344
[email protected]d9da5fe2010-10-13 22:37:164345 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034346 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514347 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074348 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:064349 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164350
[email protected]262eec82013-03-19 21:01:364351 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504352 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164353
bncce36dca22015-04-21 22:11:234354 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344355 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234356 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
4357 // fetch https://www.example.org/ via SPDY
4358 const char kMyUrl[] = "https://www.example.org/";
[email protected]cdf8f7e72013-05-23 10:56:464359 scoped_ptr<SpdyFrame> get(
4360 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
[email protected]23e482282013-06-14 16:08:024361 scoped_ptr<SpdyFrame> wrapped_get(
4362 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
4363 scoped_ptr<SpdyFrame> conn_resp(
4364 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4365 scoped_ptr<SpdyFrame> get_resp(
4366 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:194367 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:024368 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
4369 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4370 scoped_ptr<SpdyFrame> wrapped_body(
4371 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
[email protected]ff98d7f02012-03-22 21:44:194372 scoped_ptr<SpdyFrame> window_update_get_resp(
[email protected]c10b20852013-05-15 21:29:204373 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
[email protected]ff98d7f02012-03-22 21:44:194374 scoped_ptr<SpdyFrame> window_update_body(
[email protected]c10b20852013-05-15 21:29:204375 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
[email protected]8d2f7012012-02-16 00:08:044376
4377 MockWrite spdy_writes[] = {
rch32320842015-05-16 15:57:094378 CreateMockWrite(*connect, 0),
4379 CreateMockWrite(*wrapped_get, 2),
4380 CreateMockWrite(*window_update_get_resp, 6),
[email protected]8d2f7012012-02-16 00:08:044381 CreateMockWrite(*window_update_body, 7),
4382 };
4383
[email protected]d9da5fe2010-10-13 22:37:164384 MockRead spdy_reads[] = {
rch32320842015-05-16 15:57:094385 CreateMockRead(*conn_resp, 1, ASYNC),
4386 MockRead(ASYNC, ERR_IO_PENDING, 3),
rch8e6c6c42015-05-01 14:05:134387 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
rch32320842015-05-16 15:57:094388 CreateMockRead(*wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:134389 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:164390 };
4391
rch32320842015-05-16 15:57:094392 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4393 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074394 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164395
[email protected]8ddf8322012-02-23 18:08:064396 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:024397 ssl.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:074398 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064399 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:024400 ssl2.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:074401 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164402
[email protected]49639fa2011-12-20 23:22:414403 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164404
[email protected]49639fa2011-12-20 23:22:414405 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164406 EXPECT_EQ(ERR_IO_PENDING, rv);
4407
rch32320842015-05-16 15:57:094408 // Allow the SpdyProxyClientSocket's write callback to complete.
4409 base::MessageLoop::current()->RunUntilIdle();
4410 // Now allow the read of the response to complete.
4411 spdy_data.CompleteRead();
[email protected]d9da5fe2010-10-13 22:37:164412 rv = callback1.WaitForResult();
4413 EXPECT_EQ(OK, rv);
4414
[email protected]58e32bb2013-01-21 18:23:254415 LoadTimingInfo load_timing_info;
4416 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4417 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4418
[email protected]d9da5fe2010-10-13 22:37:164419 const HttpResponseInfo* response = trans->GetResponseInfo();
4420 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504421 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]d9da5fe2010-10-13 22:37:164422 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4423
4424 std::string response_data;
4425 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]448d4ca52012-03-04 04:12:234426 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:164427}
4428
4429// Test a SPDY CONNECT failure through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024430TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:274431 HttpRequestInfo request;
4432 request.method = "GET";
bncce36dca22015-04-21 22:11:234433 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274434 request.load_flags = 0;
4435
[email protected]d9da5fe2010-10-13 22:37:164436 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034437 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514438 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074439 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:064440 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164441
[email protected]262eec82013-03-19 21:01:364442 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504443 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164444
bncce36dca22015-04-21 22:11:234445 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344446 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234447 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:204448 scoped_ptr<SpdyFrame> get(
4449 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:164450
4451 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134452 CreateMockWrite(*connect, 0), CreateMockWrite(*get, 2),
[email protected]d9da5fe2010-10-13 22:37:164453 };
4454
[email protected]23e482282013-06-14 16:08:024455 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
4456 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:164457 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134458 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:164459 };
4460
rch8e6c6c42015-05-01 14:05:134461 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4462 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074463 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164464
[email protected]8ddf8322012-02-23 18:08:064465 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:024466 ssl.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:074467 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064468 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:024469 ssl2.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:074470 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164471
[email protected]49639fa2011-12-20 23:22:414472 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164473
[email protected]49639fa2011-12-20 23:22:414474 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164475 EXPECT_EQ(ERR_IO_PENDING, rv);
4476
4477 rv = callback1.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:174478 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]d9da5fe2010-10-13 22:37:164479
[email protected]4eddbc732012-08-09 05:40:174480 // TODO(ttuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:164481}
4482
[email protected]f6c63db52013-02-02 00:35:224483// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4484// HTTPS Proxy to different servers.
[email protected]23e482282013-06-14 16:08:024485TEST_P(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:224486 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
4487 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034488 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514489 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074490 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:064491 scoped_refptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504492 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224493
4494 HttpRequestInfo request1;
4495 request1.method = "GET";
bncce36dca22015-04-21 22:11:234496 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224497 request1.load_flags = 0;
4498
4499 HttpRequestInfo request2;
4500 request2.method = "GET";
bncce36dca22015-04-21 22:11:234501 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:224502 request2.load_flags = 0;
4503
bncce36dca22015-04-21 22:11:234504 // CONNECT to www.example.org:443 via SPDY.
lgarrona91df87f2014-12-05 00:51:344505 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234506 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]23e482282013-06-14 16:08:024507 scoped_ptr<SpdyFrame> conn_resp1(
4508 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f6c63db52013-02-02 00:35:224509
bncce36dca22015-04-21 22:11:234510 // Fetch https://www.example.org/ via HTTP.
4511 const char get1[] =
4512 "GET / HTTP/1.1\r\n"
4513 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224514 "Connection: keep-alive\r\n\r\n";
4515 scoped_ptr<SpdyFrame> wrapped_get1(
[email protected]23e482282013-06-14 16:08:024516 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
[email protected]f6c63db52013-02-02 00:35:224517 const char resp1[] = "HTTP/1.1 200 OK\r\n"
4518 "Content-Length: 1\r\n\r\n";
4519 scoped_ptr<SpdyFrame> wrapped_get_resp1(
[email protected]23e482282013-06-14 16:08:024520 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
4521 scoped_ptr<SpdyFrame> wrapped_body1(
4522 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
[email protected]f6c63db52013-02-02 00:35:224523 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204524 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
[email protected]f6c63db52013-02-02 00:35:224525
bncce36dca22015-04-21 22:11:234526 // CONNECT to mail.example.org:443 via SPDY.
[email protected]745aa9c2014-06-27 02:21:294527 SpdyHeaderBlock connect2_block;
bnc7ecc1122015-09-28 13:22:494528 spdy_util_.MaybeAddVersionHeader(&connect2_block);
[email protected]745aa9c2014-06-27 02:21:294529 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
bnc9b79a572015-09-02 12:25:034530 if (GetParam() == kProtoHTTP2) {
bnc6b996d532015-07-29 10:51:324531 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org:443";
4532 } else {
bnc6b996d532015-07-29 10:51:324533 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org";
bnc7ecc1122015-09-28 13:22:494534 connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443";
bnc6b996d532015-07-29 10:51:324535 }
[email protected]f6c63db52013-02-02 00:35:224536 scoped_ptr<SpdyFrame> connect2(
[email protected]745aa9c2014-06-27 02:21:294537 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
[email protected]601e03f12014-04-06 16:26:394538
[email protected]23e482282013-06-14 16:08:024539 scoped_ptr<SpdyFrame> conn_resp2(
4540 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]f6c63db52013-02-02 00:35:224541
bncce36dca22015-04-21 22:11:234542 // Fetch https://mail.example.org/ via HTTP.
4543 const char get2[] =
4544 "GET / HTTP/1.1\r\n"
4545 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224546 "Connection: keep-alive\r\n\r\n";
4547 scoped_ptr<SpdyFrame> wrapped_get2(
[email protected]23e482282013-06-14 16:08:024548 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
[email protected]f6c63db52013-02-02 00:35:224549 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4550 "Content-Length: 2\r\n\r\n";
4551 scoped_ptr<SpdyFrame> wrapped_get_resp2(
[email protected]23e482282013-06-14 16:08:024552 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
[email protected]f6c63db52013-02-02 00:35:224553 scoped_ptr<SpdyFrame> wrapped_body2(
[email protected]23e482282013-06-14 16:08:024554 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
[email protected]f6c63db52013-02-02 00:35:224555
4556 MockWrite spdy_writes[] = {
4557 CreateMockWrite(*connect1, 0),
4558 CreateMockWrite(*wrapped_get1, 2),
4559 CreateMockWrite(*connect2, 5),
4560 CreateMockWrite(*wrapped_get2, 7),
4561 };
4562
4563 MockRead spdy_reads[] = {
4564 CreateMockRead(*conn_resp1, 1, ASYNC),
4565 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4566 CreateMockRead(*wrapped_body1, 4, ASYNC),
4567 CreateMockRead(*conn_resp2, 6, ASYNC),
4568 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
4569 CreateMockRead(*wrapped_body2, 9, ASYNC),
4570 MockRead(ASYNC, 0, 10),
4571 };
4572
mmenke11eb5152015-06-09 14:50:504573 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4574 arraysize(spdy_writes));
4575 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224576
4577 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:024578 ssl.SetNextProto(GetParam());
mmenke11eb5152015-06-09 14:50:504579 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224580 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504581 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:224582 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504583 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:224584
4585 TestCompletionCallback callback;
4586
[email protected]262eec82013-03-19 21:01:364587 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504588 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224589 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504590 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224591
4592 LoadTimingInfo load_timing_info;
4593 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4594 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4595
4596 const HttpResponseInfo* response = trans->GetResponseInfo();
4597 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504598 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]f6c63db52013-02-02 00:35:224599 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4600
4601 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:294602 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
mmenke11eb5152015-06-09 14:50:504603 rv = trans->Read(buf.get(), 256, callback.callback());
4604 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224605
[email protected]262eec82013-03-19 21:01:364606 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504607 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224608 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504609 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224610
4611 LoadTimingInfo load_timing_info2;
4612 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4613 // Even though the SPDY connection is reused, a new tunnelled connection has
4614 // to be created, so the socket's load timing looks like a fresh connection.
4615 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
4616
4617 // The requests should have different IDs, since they each are using their own
4618 // separate stream.
4619 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4620
mmenke11eb5152015-06-09 14:50:504621 rv = trans2->Read(buf.get(), 256, callback.callback());
4622 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224623}
4624
4625// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4626// HTTPS Proxy to the same server.
[email protected]23e482282013-06-14 16:08:024627TEST_P(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:224628 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
4629 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034630 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514631 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074632 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:064633 scoped_refptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504634 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224635
4636 HttpRequestInfo request1;
4637 request1.method = "GET";
bncce36dca22015-04-21 22:11:234638 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224639 request1.load_flags = 0;
4640
4641 HttpRequestInfo request2;
4642 request2.method = "GET";
bncce36dca22015-04-21 22:11:234643 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:224644 request2.load_flags = 0;
4645
bncce36dca22015-04-21 22:11:234646 // CONNECT to www.example.org:443 via SPDY.
lgarrona91df87f2014-12-05 00:51:344647 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234648 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]23e482282013-06-14 16:08:024649 scoped_ptr<SpdyFrame> conn_resp1(
4650 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f6c63db52013-02-02 00:35:224651
bncce36dca22015-04-21 22:11:234652 // Fetch https://www.example.org/ via HTTP.
4653 const char get1[] =
4654 "GET / HTTP/1.1\r\n"
4655 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224656 "Connection: keep-alive\r\n\r\n";
4657 scoped_ptr<SpdyFrame> wrapped_get1(
[email protected]23e482282013-06-14 16:08:024658 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
[email protected]f6c63db52013-02-02 00:35:224659 const char resp1[] = "HTTP/1.1 200 OK\r\n"
4660 "Content-Length: 1\r\n\r\n";
4661 scoped_ptr<SpdyFrame> wrapped_get_resp1(
[email protected]23e482282013-06-14 16:08:024662 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
4663 scoped_ptr<SpdyFrame> wrapped_body1(
4664 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
[email protected]f6c63db52013-02-02 00:35:224665 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204666 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
[email protected]f6c63db52013-02-02 00:35:224667
bncce36dca22015-04-21 22:11:234668 // Fetch https://www.example.org/2 via HTTP.
4669 const char get2[] =
4670 "GET /2 HTTP/1.1\r\n"
4671 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224672 "Connection: keep-alive\r\n\r\n";
4673 scoped_ptr<SpdyFrame> wrapped_get2(
[email protected]23e482282013-06-14 16:08:024674 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
[email protected]f6c63db52013-02-02 00:35:224675 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4676 "Content-Length: 2\r\n\r\n";
4677 scoped_ptr<SpdyFrame> wrapped_get_resp2(
[email protected]23e482282013-06-14 16:08:024678 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
[email protected]f6c63db52013-02-02 00:35:224679 scoped_ptr<SpdyFrame> wrapped_body2(
[email protected]23e482282013-06-14 16:08:024680 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
[email protected]f6c63db52013-02-02 00:35:224681
4682 MockWrite spdy_writes[] = {
4683 CreateMockWrite(*connect1, 0),
4684 CreateMockWrite(*wrapped_get1, 2),
4685 CreateMockWrite(*wrapped_get2, 5),
4686 };
4687
4688 MockRead spdy_reads[] = {
4689 CreateMockRead(*conn_resp1, 1, ASYNC),
4690 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4691 CreateMockRead(*wrapped_body1, 4, ASYNC),
4692 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
4693 CreateMockRead(*wrapped_body2, 7, ASYNC),
4694 MockRead(ASYNC, 0, 8),
4695 };
4696
mmenke11eb5152015-06-09 14:50:504697 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4698 arraysize(spdy_writes));
4699 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224700
4701 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:024702 ssl.SetNextProto(GetParam());
mmenke11eb5152015-06-09 14:50:504703 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224704 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504705 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:224706
4707 TestCompletionCallback callback;
4708
[email protected]262eec82013-03-19 21:01:364709 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504710 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224711 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4712 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f6c63db52013-02-02 00:35:224713
4714 rv = callback.WaitForResult();
4715 EXPECT_EQ(OK, rv);
4716
4717 LoadTimingInfo load_timing_info;
4718 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4719 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4720
4721 const HttpResponseInfo* response = trans->GetResponseInfo();
4722 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504723 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]f6c63db52013-02-02 00:35:224724 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4725
4726 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:294727 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
[email protected]90499482013-06-01 00:39:504728 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:224729 trans.reset();
4730
[email protected]262eec82013-03-19 21:01:364731 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504732 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224733 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4734 EXPECT_EQ(ERR_IO_PENDING, rv);
4735
[email protected]f6c63db52013-02-02 00:35:224736 rv = callback.WaitForResult();
4737 EXPECT_EQ(OK, rv);
4738
4739 LoadTimingInfo load_timing_info2;
4740 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4741 TestLoadTimingReused(load_timing_info2);
4742
4743 // The requests should have the same ID.
4744 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4745
[email protected]90499482013-06-01 00:39:504746 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:224747}
4748
4749// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4750// Proxy to different servers.
mmenke11eb5152015-06-09 14:50:504751TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:224752 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034753 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514754 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074755 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:064756 scoped_refptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504757 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224758
4759 HttpRequestInfo request1;
4760 request1.method = "GET";
bncce36dca22015-04-21 22:11:234761 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224762 request1.load_flags = 0;
4763
4764 HttpRequestInfo request2;
4765 request2.method = "GET";
bncce36dca22015-04-21 22:11:234766 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:224767 request2.load_flags = 0;
4768
bncce36dca22015-04-21 22:11:234769 // http://www.example.org/
[email protected]23e482282013-06-14 16:08:024770 scoped_ptr<SpdyHeaderBlock> headers(
bncce36dca22015-04-21 22:11:234771 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
[email protected]745aa9c2014-06-27 02:21:294772 scoped_ptr<SpdyFrame> get1(
4773 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]23e482282013-06-14 16:08:024774 scoped_ptr<SpdyFrame> get_resp1(
4775 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4776 scoped_ptr<SpdyFrame> body1(
4777 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
[email protected]f6c63db52013-02-02 00:35:224778
bncce36dca22015-04-21 22:11:234779 // http://mail.example.org/
[email protected]23e482282013-06-14 16:08:024780 scoped_ptr<SpdyHeaderBlock> headers2(
bncce36dca22015-04-21 22:11:234781 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
[email protected]745aa9c2014-06-27 02:21:294782 scoped_ptr<SpdyFrame> get2(
4783 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
[email protected]23e482282013-06-14 16:08:024784 scoped_ptr<SpdyFrame> get_resp2(
4785 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4786 scoped_ptr<SpdyFrame> body2(
4787 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
[email protected]f6c63db52013-02-02 00:35:224788
4789 MockWrite spdy_writes[] = {
4790 CreateMockWrite(*get1, 0),
4791 CreateMockWrite(*get2, 3),
4792 };
4793
4794 MockRead spdy_reads[] = {
4795 CreateMockRead(*get_resp1, 1, ASYNC),
4796 CreateMockRead(*body1, 2, ASYNC),
4797 CreateMockRead(*get_resp2, 4, ASYNC),
4798 CreateMockRead(*body2, 5, ASYNC),
4799 MockRead(ASYNC, 0, 6),
4800 };
4801
mmenke11eb5152015-06-09 14:50:504802 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4803 arraysize(spdy_writes));
4804 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224805
4806 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:024807 ssl.SetNextProto(GetParam());
mmenke11eb5152015-06-09 14:50:504808 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224809
4810 TestCompletionCallback callback;
4811
[email protected]262eec82013-03-19 21:01:364812 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504813 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224814 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504815 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224816
4817 LoadTimingInfo load_timing_info;
4818 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4819 TestLoadTimingNotReused(load_timing_info,
4820 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4821
4822 const HttpResponseInfo* response = trans->GetResponseInfo();
4823 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504824 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]f6c63db52013-02-02 00:35:224825 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4826
4827 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:294828 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
mmenke11eb5152015-06-09 14:50:504829 rv = trans->Read(buf.get(), 256, callback.callback());
4830 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224831 // Delete the first request, so the second one can reuse the socket.
4832 trans.reset();
4833
[email protected]262eec82013-03-19 21:01:364834 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504835 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224836 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504837 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224838
4839 LoadTimingInfo load_timing_info2;
4840 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4841 TestLoadTimingReused(load_timing_info2);
4842
4843 // The requests should have the same ID.
4844 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4845
mmenke11eb5152015-06-09 14:50:504846 rv = trans2->Read(buf.get(), 256, callback.callback());
4847 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224848}
4849
[email protected]2df19bb2010-08-25 20:13:464850// Test the challenge-response-retry sequence through an HTTPS Proxy
[email protected]23e482282013-06-14 16:08:024851TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:464852 HttpRequestInfo request;
4853 request.method = "GET";
bncce36dca22015-04-21 22:11:234854 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:464855 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:294856 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2df19bb2010-08-25 20:13:464857
[email protected]79cb5c12011-09-12 13:12:044858 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034859 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:514860 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074861 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:064862 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:274863
[email protected]2df19bb2010-08-25 20:13:464864 // Since we have proxy, should use full url
4865 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234866 MockWrite(
4867 "GET http://www.example.org/ HTTP/1.1\r\n"
4868 "Host: www.example.org\r\n"
4869 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:464870
bncce36dca22015-04-21 22:11:234871 // After calling trans->RestartWithAuth(), this is the request we should
4872 // be issuing -- the final header line contains the credentials.
4873 MockWrite(
4874 "GET http://www.example.org/ HTTP/1.1\r\n"
4875 "Host: www.example.org\r\n"
4876 "Proxy-Connection: keep-alive\r\n"
4877 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:464878 };
4879
4880 // The proxy responds to the GET with a 407, using a persistent
4881 // connection.
4882 MockRead data_reads1[] = {
4883 // No credentials.
4884 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4885 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4886 MockRead("Proxy-Connection: keep-alive\r\n"),
4887 MockRead("Content-Length: 0\r\n\r\n"),
4888
4889 MockRead("HTTP/1.1 200 OK\r\n"),
4890 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4891 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064892 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:464893 };
4894
4895 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4896 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074897 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064898 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074899 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:464900
[email protected]49639fa2011-12-20 23:22:414901 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:464902
[email protected]262eec82013-03-19 21:01:364903 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504904 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504905
[email protected]49639fa2011-12-20 23:22:414906 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:464907 EXPECT_EQ(ERR_IO_PENDING, rv);
4908
4909 rv = callback1.WaitForResult();
4910 EXPECT_EQ(OK, rv);
4911
[email protected]58e32bb2013-01-21 18:23:254912 LoadTimingInfo load_timing_info;
4913 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4914 TestLoadTimingNotReused(load_timing_info,
4915 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4916
[email protected]2df19bb2010-08-25 20:13:464917 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504918 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504919 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]2df19bb2010-08-25 20:13:464920 EXPECT_EQ(407, response->headers->response_code());
4921 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:044922 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2df19bb2010-08-25 20:13:464923
[email protected]49639fa2011-12-20 23:22:414924 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:464925
[email protected]49639fa2011-12-20 23:22:414926 rv = trans->RestartWithAuth(
4927 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]2df19bb2010-08-25 20:13:464928 EXPECT_EQ(ERR_IO_PENDING, rv);
4929
4930 rv = callback2.WaitForResult();
4931 EXPECT_EQ(OK, rv);
4932
[email protected]58e32bb2013-01-21 18:23:254933 load_timing_info = LoadTimingInfo();
4934 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4935 // Retrying with HTTP AUTH is considered to be reusing a socket.
4936 TestLoadTimingReused(load_timing_info);
4937
[email protected]2df19bb2010-08-25 20:13:464938 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504939 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464940
4941 EXPECT_TRUE(response->headers->IsKeepAlive());
4942 EXPECT_EQ(200, response->headers->response_code());
4943 EXPECT_EQ(100, response->headers->GetContentLength());
4944 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4945
4946 // The password prompt info should not be set.
4947 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4948}
4949
[email protected]23e482282013-06-14 16:08:024950void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:084951 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:424952 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:084953 request.method = "GET";
bncce36dca22015-04-21 22:11:234954 request.url = GURL("https://www.example.org/");
[email protected]c744cf22009-02-27 07:28:084955 request.load_flags = 0;
4956
[email protected]cb9bf6ca2011-01-28 13:15:274957 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034958 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenke6b3af6e2015-09-12 02:06:064959 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:274960
[email protected]c744cf22009-02-27 07:28:084961 // Since we have proxy, should try to establish tunnel.
4962 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:234963 MockWrite(
4964 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4965 "Host: www.example.org\r\n"
4966 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:084967 };
4968
4969 MockRead data_reads[] = {
4970 status,
4971 MockRead("Content-Length: 10\r\n\r\n"),
4972 // No response body because the test stops reading here.
[email protected]8ddf8322012-02-23 18:08:064973 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:084974 };
4975
[email protected]31a2bfe2010-02-09 08:03:394976 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4977 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:074978 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:084979
[email protected]49639fa2011-12-20 23:22:414980 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:084981
[email protected]262eec82013-03-19 21:01:364982 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504983 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504984
[email protected]49639fa2011-12-20 23:22:414985 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424986 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:084987
4988 rv = callback.WaitForResult();
4989 EXPECT_EQ(expected_status, rv);
4990}
4991
[email protected]23e482282013-06-14 16:08:024992void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:234993 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:084994 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:424995 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:084996}
4997
[email protected]23e482282013-06-14 16:08:024998TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:084999 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
5000}
5001
[email protected]23e482282013-06-14 16:08:025002TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:085003 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
5004}
5005
[email protected]23e482282013-06-14 16:08:025006TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:085007 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
5008}
5009
[email protected]23e482282013-06-14 16:08:025010TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:085011 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
5012}
5013
[email protected]23e482282013-06-14 16:08:025014TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:085015 ConnectStatusHelper(
5016 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
5017}
5018
[email protected]23e482282013-06-14 16:08:025019TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:085020 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
5021}
5022
[email protected]23e482282013-06-14 16:08:025023TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:085024 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
5025}
5026
[email protected]23e482282013-06-14 16:08:025027TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:085028 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
5029}
5030
[email protected]23e482282013-06-14 16:08:025031TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:085032 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
5033}
5034
[email protected]23e482282013-06-14 16:08:025035TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:085036 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
5037}
5038
[email protected]23e482282013-06-14 16:08:025039TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:085040 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
5041}
5042
[email protected]23e482282013-06-14 16:08:025043TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:085044 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
5045}
5046
[email protected]23e482282013-06-14 16:08:025047TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:085048 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
5049}
5050
[email protected]23e482282013-06-14 16:08:025051TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:085052 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
5053}
5054
[email protected]23e482282013-06-14 16:08:025055TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:085056 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
5057}
5058
[email protected]23e482282013-06-14 16:08:025059TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:085060 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
5061}
5062
[email protected]0a17aab32014-04-24 03:32:375063TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
5064 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
5065}
5066
[email protected]23e482282013-06-14 16:08:025067TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:085068 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
5069}
5070
[email protected]23e482282013-06-14 16:08:025071TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:085072 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
5073}
5074
[email protected]23e482282013-06-14 16:08:025075TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:085076 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
5077}
5078
[email protected]23e482282013-06-14 16:08:025079TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:085080 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
5081}
5082
[email protected]23e482282013-06-14 16:08:025083TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:085084 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
5085}
5086
[email protected]23e482282013-06-14 16:08:025087TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:085088 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
5089}
5090
[email protected]23e482282013-06-14 16:08:025091TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:085092 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
5093}
5094
[email protected]23e482282013-06-14 16:08:025095TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:085096 ConnectStatusHelperWithExpectedStatus(
5097 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:545098 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:085099}
5100
[email protected]23e482282013-06-14 16:08:025101TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:085102 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
5103}
5104
[email protected]23e482282013-06-14 16:08:025105TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:085106 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
5107}
5108
[email protected]23e482282013-06-14 16:08:025109TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:085110 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
5111}
5112
[email protected]23e482282013-06-14 16:08:025113TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:085114 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
5115}
5116
[email protected]23e482282013-06-14 16:08:025117TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:085118 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
5119}
5120
[email protected]23e482282013-06-14 16:08:025121TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:085122 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
5123}
5124
[email protected]23e482282013-06-14 16:08:025125TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:085126 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
5127}
5128
[email protected]23e482282013-06-14 16:08:025129TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:085130 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
5131}
5132
[email protected]23e482282013-06-14 16:08:025133TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:085134 ConnectStatusHelper(
5135 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
5136}
5137
[email protected]23e482282013-06-14 16:08:025138TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:085139 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
5140}
5141
[email protected]23e482282013-06-14 16:08:025142TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:085143 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
5144}
5145
[email protected]23e482282013-06-14 16:08:025146TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:085147 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
5148}
5149
[email protected]23e482282013-06-14 16:08:025150TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:085151 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
5152}
5153
[email protected]23e482282013-06-14 16:08:025154TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:085155 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
5156}
5157
[email protected]23e482282013-06-14 16:08:025158TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:085159 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
5160}
5161
[email protected]23e482282013-06-14 16:08:025162TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:085163 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
5164}
5165
[email protected]038e9a32008-10-08 22:40:165166// Test the flow when both the proxy server AND origin server require
5167// authentication. Again, this uses basic auth for both since that is
5168// the simplest to mock.
[email protected]23e482282013-06-14 16:08:025169TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:275170 HttpRequestInfo request;
5171 request.method = "GET";
bncce36dca22015-04-21 22:11:235172 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:275173 request.load_flags = 0;
5174
[email protected]038e9a32008-10-08 22:40:165175 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035176 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenke6b3af6e2015-09-12 02:06:065177 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:075178
5179 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:415180 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]038e9a32008-10-08 22:40:165181
[email protected]f9ee6b52008-11-08 06:46:235182 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235183 MockWrite(
5184 "GET http://www.example.org/ HTTP/1.1\r\n"
5185 "Host: www.example.org\r\n"
5186 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:235187 };
5188
[email protected]038e9a32008-10-08 22:40:165189 MockRead data_reads1[] = {
5190 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
5191 // Give a couple authenticate options (only the middle one is actually
5192 // supported).
[email protected]22927ad2009-09-21 19:56:195193 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:165194 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5195 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
5196 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5197 // Large content-length -- won't matter, as connection will be reset.
5198 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065199 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:165200 };
5201
5202 // After calling trans->RestartWithAuth() the first time, this is the
5203 // request we should be issuing -- the final header line contains the
5204 // proxy's credentials.
5205 MockWrite data_writes2[] = {
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"
5210 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:165211 };
5212
5213 // Now the proxy server lets the request pass through to origin server.
5214 // The origin server responds with a 401.
5215 MockRead data_reads2[] = {
5216 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5217 // Note: We are using the same realm-name as the proxy server. This is
5218 // completely valid, as realms are unique across hosts.
5219 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5220 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5221 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065222 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:165223 };
5224
5225 // After calling trans->RestartWithAuth() the second time, we should send
5226 // the credentials for both the proxy and origin server.
5227 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:235228 MockWrite(
5229 "GET http://www.example.org/ HTTP/1.1\r\n"
5230 "Host: www.example.org\r\n"
5231 "Proxy-Connection: keep-alive\r\n"
5232 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
5233 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:165234 };
5235
5236 // Lastly we get the desired content.
5237 MockRead data_reads3[] = {
5238 MockRead("HTTP/1.0 200 OK\r\n"),
5239 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5240 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065241 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:165242 };
5243
[email protected]31a2bfe2010-02-09 08:03:395244 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5245 data_writes1, arraysize(data_writes1));
5246 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5247 data_writes2, arraysize(data_writes2));
5248 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5249 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:075250 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5251 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5252 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:165253
[email protected]49639fa2011-12-20 23:22:415254 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:165255
[email protected]49639fa2011-12-20 23:22:415256 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425257 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165258
5259 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425260 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165261
[email protected]1c773ea12009-04-28 19:58:425262 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505263 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045264 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:165265
[email protected]49639fa2011-12-20 23:22:415266 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:165267
[email protected]49639fa2011-12-20 23:22:415268 rv = trans->RestartWithAuth(
5269 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:425270 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165271
5272 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425273 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165274
5275 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505276 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045277 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:165278
[email protected]49639fa2011-12-20 23:22:415279 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:165280
[email protected]49639fa2011-12-20 23:22:415281 rv = trans->RestartWithAuth(
5282 AuthCredentials(kFoo2, kBar2), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425283 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165284
5285 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425286 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165287
5288 response = trans->GetResponseInfo();
5289 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5290 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:165291}
[email protected]4ddaf2502008-10-23 18:26:195292
[email protected]ea9dc9a2009-09-05 00:43:325293// For the NTLM implementation using SSPI, we skip the NTLM tests since we
5294// can't hook into its internals to cause it to generate predictable NTLM
5295// authorization headers.
5296#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:295297// The NTLM authentication unit tests were generated by capturing the HTTP
5298// requests and responses using Fiddler 2 and inspecting the generated random
5299// bytes in the debugger.
5300
5301// Enter the correct password and authenticate successfully.
[email protected]23e482282013-06-14 16:08:025302TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:425303 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:245304 request.method = "GET";
5305 request.url = GURL("http://172.22.68.17/kids/login.aspx");
[email protected]2217aa22013-10-11 03:03:545306
5307 // Ensure load is not disrupted by flags which suppress behaviour specific
5308 // to other auth schemes.
5309 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:245310
[email protected]cb9bf6ca2011-01-28 13:15:275311 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
5312 MockGetHostName);
mmenke6b3af6e2015-09-12 02:06:065313 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275314
[email protected]3f918782009-02-28 01:29:245315 MockWrite data_writes1[] = {
5316 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5317 "Host: 172.22.68.17\r\n"
5318 "Connection: keep-alive\r\n\r\n"),
5319 };
5320
5321 MockRead data_reads1[] = {
5322 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:045323 // Negotiate and NTLM are often requested together. However, we only want
5324 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
5325 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:245326 MockRead("WWW-Authenticate: NTLM\r\n"),
5327 MockRead("Connection: close\r\n"),
5328 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365329 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245330 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065331 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:245332 };
5333
5334 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:225335 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:245336 // request we should be issuing -- the final header line contains a Type
5337 // 1 message.
5338 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5339 "Host: 172.22.68.17\r\n"
5340 "Connection: keep-alive\r\n"
5341 "Authorization: NTLM "
5342 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5343
5344 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5345 // (the credentials for the origin server). The second request continues
5346 // on the same connection.
5347 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5348 "Host: 172.22.68.17\r\n"
5349 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:295350 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5351 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5352 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
5353 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
5354 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245355 };
5356
5357 MockRead data_reads2[] = {
5358 // The origin server responds with a Type 2 message.
5359 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5360 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:295361 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:245362 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5363 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5364 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5365 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5366 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5367 "BtAAAAAAA=\r\n"),
5368 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365369 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245370 MockRead("You are not authorized to view this page\r\n"),
5371
5372 // Lastly we get the desired content.
5373 MockRead("HTTP/1.1 200 OK\r\n"),
5374 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
5375 MockRead("Content-Length: 13\r\n\r\n"),
5376 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:065377 MockRead(SYNCHRONOUS, OK),
[email protected]3f918782009-02-28 01:29:245378 };
5379
[email protected]31a2bfe2010-02-09 08:03:395380 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5381 data_writes1, arraysize(data_writes1));
5382 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5383 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:075384 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5385 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:245386
[email protected]49639fa2011-12-20 23:22:415387 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:245388
[email protected]262eec82013-03-19 21:01:365389 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505390 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505391
[email protected]49639fa2011-12-20 23:22:415392 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425393 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:245394
5395 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425396 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:245397
[email protected]0757e7702009-03-27 04:00:225398 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5399
[email protected]1c773ea12009-04-28 19:58:425400 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:045401 ASSERT_FALSE(response == NULL);
5402 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]3f918782009-02-28 01:29:245403
[email protected]49639fa2011-12-20 23:22:415404 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:255405
[email protected]f3cf9802011-10-28 18:44:585406 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:415407 callback2.callback());
[email protected]10af5fe72011-01-31 16:17:255408 EXPECT_EQ(ERR_IO_PENDING, rv);
5409
5410 rv = callback2.WaitForResult();
5411 EXPECT_EQ(OK, rv);
5412
5413 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5414
5415 response = trans->GetResponseInfo();
5416 ASSERT_TRUE(response != NULL);
[email protected]10af5fe72011-01-31 16:17:255417 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5418
[email protected]49639fa2011-12-20 23:22:415419 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:245420
[email protected]49639fa2011-12-20 23:22:415421 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425422 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:245423
[email protected]0757e7702009-03-27 04:00:225424 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425425 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:245426
5427 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505428 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:245429 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5430 EXPECT_EQ(13, response->headers->GetContentLength());
5431}
5432
[email protected]385a4672009-03-11 22:21:295433// Enter a wrong password, and then the correct one.
[email protected]23e482282013-06-14 16:08:025434TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:425435 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:295436 request.method = "GET";
5437 request.url = GURL("http://172.22.68.17/kids/login.aspx");
5438 request.load_flags = 0;
5439
[email protected]cb9bf6ca2011-01-28 13:15:275440 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
5441 MockGetHostName);
mmenke6b3af6e2015-09-12 02:06:065442 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275443
[email protected]385a4672009-03-11 22:21:295444 MockWrite data_writes1[] = {
5445 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5446 "Host: 172.22.68.17\r\n"
5447 "Connection: keep-alive\r\n\r\n"),
5448 };
5449
5450 MockRead data_reads1[] = {
5451 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:045452 // Negotiate and NTLM are often requested together. However, we only want
5453 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
5454 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:295455 MockRead("WWW-Authenticate: NTLM\r\n"),
5456 MockRead("Connection: close\r\n"),
5457 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365458 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295459 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065460 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:295461 };
5462
5463 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:225464 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:295465 // request we should be issuing -- the final header line contains a Type
5466 // 1 message.
5467 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5468 "Host: 172.22.68.17\r\n"
5469 "Connection: keep-alive\r\n"
5470 "Authorization: NTLM "
5471 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5472
5473 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5474 // (the credentials for the origin server). The second request continues
5475 // on the same connection.
5476 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5477 "Host: 172.22.68.17\r\n"
5478 "Connection: keep-alive\r\n"
5479 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5480 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5481 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
5482 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
5483 "4Ww7b7E=\r\n\r\n"),
5484 };
5485
5486 MockRead data_reads2[] = {
5487 // The origin server responds with a Type 2 message.
5488 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5489 MockRead("WWW-Authenticate: NTLM "
5490 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
5491 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5492 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5493 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5494 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5495 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5496 "BtAAAAAAA=\r\n"),
5497 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365498 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295499 MockRead("You are not authorized to view this page\r\n"),
5500
5501 // Wrong password.
5502 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:295503 MockRead("WWW-Authenticate: NTLM\r\n"),
5504 MockRead("Connection: close\r\n"),
5505 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365506 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295507 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065508 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:295509 };
5510
5511 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:225512 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:295513 // request we should be issuing -- the final header line contains a Type
5514 // 1 message.
5515 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5516 "Host: 172.22.68.17\r\n"
5517 "Connection: keep-alive\r\n"
5518 "Authorization: NTLM "
5519 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5520
5521 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5522 // (the credentials for the origin server). The second request continues
5523 // on the same connection.
5524 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5525 "Host: 172.22.68.17\r\n"
5526 "Connection: keep-alive\r\n"
5527 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5528 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5529 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
5530 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
5531 "+4MUm7c=\r\n\r\n"),
5532 };
5533
5534 MockRead data_reads3[] = {
5535 // The origin server responds with a Type 2 message.
5536 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5537 MockRead("WWW-Authenticate: NTLM "
5538 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
5539 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5540 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5541 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5542 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5543 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5544 "BtAAAAAAA=\r\n"),
5545 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365546 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295547 MockRead("You are not authorized to view this page\r\n"),
5548
5549 // Lastly we get the desired content.
5550 MockRead("HTTP/1.1 200 OK\r\n"),
5551 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
5552 MockRead("Content-Length: 13\r\n\r\n"),
5553 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:065554 MockRead(SYNCHRONOUS, OK),
[email protected]385a4672009-03-11 22:21:295555 };
5556
[email protected]31a2bfe2010-02-09 08:03:395557 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5558 data_writes1, arraysize(data_writes1));
5559 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5560 data_writes2, arraysize(data_writes2));
5561 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5562 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:075563 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5564 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5565 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:295566
[email protected]49639fa2011-12-20 23:22:415567 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:295568
[email protected]262eec82013-03-19 21:01:365569 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505570 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505571
[email protected]49639fa2011-12-20 23:22:415572 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425573 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:295574
5575 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425576 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:295577
[email protected]0757e7702009-03-27 04:00:225578 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:295579
[email protected]1c773ea12009-04-28 19:58:425580 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505581 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045582 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]385a4672009-03-11 22:21:295583
[email protected]49639fa2011-12-20 23:22:415584 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:295585
[email protected]0757e7702009-03-27 04:00:225586 // Enter the wrong password.
[email protected]f3cf9802011-10-28 18:44:585587 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
[email protected]49639fa2011-12-20 23:22:415588 callback2.callback());
[email protected]1c773ea12009-04-28 19:58:425589 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:295590
[email protected]10af5fe72011-01-31 16:17:255591 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425592 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:295593
[email protected]0757e7702009-03-27 04:00:225594 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:415595 TestCompletionCallback callback3;
5596 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425597 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:255598 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425599 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:225600 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5601
5602 response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:045603 ASSERT_FALSE(response == NULL);
5604 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]0757e7702009-03-27 04:00:225605
[email protected]49639fa2011-12-20 23:22:415606 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:225607
5608 // Now enter the right password.
[email protected]f3cf9802011-10-28 18:44:585609 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:415610 callback4.callback());
[email protected]10af5fe72011-01-31 16:17:255611 EXPECT_EQ(ERR_IO_PENDING, rv);
5612
5613 rv = callback4.WaitForResult();
5614 EXPECT_EQ(OK, rv);
5615
5616 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5617
[email protected]49639fa2011-12-20 23:22:415618 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:255619
5620 // One more roundtrip
[email protected]49639fa2011-12-20 23:22:415621 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
[email protected]1c773ea12009-04-28 19:58:425622 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:225623
5624 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425625 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:225626
[email protected]385a4672009-03-11 22:21:295627 response = trans->GetResponseInfo();
5628 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5629 EXPECT_EQ(13, response->headers->GetContentLength());
5630}
[email protected]ea9dc9a2009-09-05 00:43:325631#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:295632
[email protected]4ddaf2502008-10-23 18:26:195633// Test reading a server response which has only headers, and no body.
5634// After some maximum number of bytes is consumed, the transaction should
5635// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
[email protected]23e482282013-06-14 16:08:025636TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:425637 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:195638 request.method = "GET";
bncce36dca22015-04-21 22:11:235639 request.url = GURL("http://www.example.org/");
[email protected]4ddaf2502008-10-23 18:26:195640 request.load_flags = 0;
5641
mmenke6b3af6e2015-09-12 02:06:065642 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275643 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:415644 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:275645
[email protected]b75b7b2f2009-10-06 00:54:535646 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:435647 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:535648 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:195649
5650 MockRead data_reads[] = {
5651 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:065652 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:195653 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:065654 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:195655 };
[email protected]31a2bfe2010-02-09 08:03:395656 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:075657 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:195658
[email protected]49639fa2011-12-20 23:22:415659 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:195660
[email protected]49639fa2011-12-20 23:22:415661 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425662 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:195663
5664 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425665 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:195666}
[email protected]f4e426b2008-11-05 00:24:495667
5668// Make sure that we don't try to reuse a TCPClientSocket when failing to
5669// establish tunnel.
5670// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]23e482282013-06-14 16:08:025671TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:235672 DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:275673 HttpRequestInfo request;
5674 request.method = "GET";
bncce36dca22015-04-21 22:11:235675 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:275676 request.load_flags = 0;
5677
[email protected]f4e426b2008-11-05 00:24:495678 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035679 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]db8f44c2008-12-13 04:52:015680
mmenke6b3af6e2015-09-12 02:06:065681 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:495682
[email protected]262eec82013-03-19 21:01:365683 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505684 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f4e426b2008-11-05 00:24:495685
[email protected]f4e426b2008-11-05 00:24:495686 // Since we have proxy, should try to establish tunnel.
5687 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235688 MockWrite(
5689 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5690 "Host: www.example.org\r\n"
5691 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:495692 };
5693
[email protected]77848d12008-11-14 00:00:225694 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:495695 // connection. Usually a proxy would return 501 (not implemented),
5696 // or 200 (tunnel established).
5697 MockRead data_reads1[] = {
5698 MockRead("HTTP/1.1 404 Not Found\r\n"),
5699 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065700 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:495701 };
5702
[email protected]31a2bfe2010-02-09 08:03:395703 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5704 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:075705 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:495706
[email protected]49639fa2011-12-20 23:22:415707 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:495708
[email protected]49639fa2011-12-20 23:22:415709 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425710 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:495711
5712 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425713 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:495714
[email protected]b4404c02009-04-10 16:38:525715 // Empty the current queue. This is necessary because idle sockets are
5716 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345717 base::MessageLoop::current()->RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:525718
[email protected]f4e426b2008-11-05 00:24:495719 // We now check to make sure the TCPClientSocket was not added back to
5720 // the pool.
[email protected]90499482013-06-01 00:39:505721 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:495722 trans.reset();
[email protected]2da659e2013-05-23 20:51:345723 base::MessageLoop::current()->RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:495724 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:505725 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:495726}
[email protected]372d34a2008-11-05 21:30:515727
[email protected]1b157c02009-04-21 01:55:405728// Make sure that we recycle a socket after reading all of the response body.
[email protected]23e482282013-06-14 16:08:025729TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:425730 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:405731 request.method = "GET";
bncce36dca22015-04-21 22:11:235732 request.url = GURL("http://www.example.org/");
[email protected]1b157c02009-04-21 01:55:405733 request.load_flags = 0;
5734
mmenke6b3af6e2015-09-12 02:06:065735 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275736
[email protected]262eec82013-03-19 21:01:365737 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505738 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:275739
[email protected]1b157c02009-04-21 01:55:405740 MockRead data_reads[] = {
5741 // A part of the response body is received with the response headers.
5742 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5743 // The rest of the response body is received in two parts.
5744 MockRead("lo"),
5745 MockRead(" world"),
5746 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:065747 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:405748 };
5749
[email protected]31a2bfe2010-02-09 08:03:395750 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:075751 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:405752
[email protected]49639fa2011-12-20 23:22:415753 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:405754
[email protected]49639fa2011-12-20 23:22:415755 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425756 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:405757
5758 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425759 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:405760
[email protected]1c773ea12009-04-28 19:58:425761 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505762 ASSERT_TRUE(response != NULL);
[email protected]1b157c02009-04-21 01:55:405763
[email protected]90499482013-06-01 00:39:505764 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]1b157c02009-04-21 01:55:405765 std::string status_line = response->headers->GetStatusLine();
5766 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
5767
[email protected]90499482013-06-01 00:39:505768 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:405769
5770 std::string response_data;
5771 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:425772 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:405773 EXPECT_EQ("hello world", response_data);
5774
5775 // Empty the current queue. This is necessary because idle sockets are
5776 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345777 base::MessageLoop::current()->RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:405778
5779 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:505780 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:405781}
5782
[email protected]76a505b2010-08-25 06:23:005783// Make sure that we recycle a SSL socket after reading all of the response
5784// body.
[email protected]23e482282013-06-14 16:08:025785TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:005786 HttpRequestInfo request;
5787 request.method = "GET";
bncce36dca22015-04-21 22:11:235788 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:005789 request.load_flags = 0;
5790
5791 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:235792 MockWrite(
5793 "GET / HTTP/1.1\r\n"
5794 "Host: www.example.org\r\n"
5795 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:005796 };
5797
5798 MockRead data_reads[] = {
5799 MockRead("HTTP/1.1 200 OK\r\n"),
5800 MockRead("Content-Length: 11\r\n\r\n"),
5801 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:065802 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:005803 };
5804
[email protected]8ddf8322012-02-23 18:08:065805 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075806 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:005807
5808 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5809 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:075810 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:005811
[email protected]49639fa2011-12-20 23:22:415812 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:005813
mmenke6b3af6e2015-09-12 02:06:065814 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:365815 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505816 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:005817
[email protected]49639fa2011-12-20 23:22:415818 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:005819
5820 EXPECT_EQ(ERR_IO_PENDING, rv);
5821 EXPECT_EQ(OK, callback.WaitForResult());
5822
5823 const HttpResponseInfo* response = trans->GetResponseInfo();
5824 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:505825 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:005826 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5827
[email protected]90499482013-06-01 00:39:505828 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:005829
5830 std::string response_data;
5831 rv = ReadTransaction(trans.get(), &response_data);
5832 EXPECT_EQ(OK, rv);
5833 EXPECT_EQ("hello world", response_data);
5834
5835 // Empty the current queue. This is necessary because idle sockets are
5836 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345837 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:005838
5839 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:505840 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:005841}
5842
5843// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5844// from the pool and make sure that we recover okay.
[email protected]23e482282013-06-14 16:08:025845TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:005846 HttpRequestInfo request;
5847 request.method = "GET";
bncce36dca22015-04-21 22:11:235848 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:005849 request.load_flags = 0;
5850
5851 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:235852 MockWrite(
5853 "GET / HTTP/1.1\r\n"
5854 "Host: www.example.org\r\n"
5855 "Connection: keep-alive\r\n\r\n"),
5856 MockWrite(
5857 "GET / HTTP/1.1\r\n"
5858 "Host: www.example.org\r\n"
5859 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:005860 };
5861
5862 MockRead data_reads[] = {
5863 MockRead("HTTP/1.1 200 OK\r\n"),
5864 MockRead("Content-Length: 11\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065865 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]76a505b2010-08-25 06:23:005866 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:065867 MockRead(ASYNC, 0, 0) // EOF
[email protected]76a505b2010-08-25 06:23:005868 };
5869
[email protected]8ddf8322012-02-23 18:08:065870 SSLSocketDataProvider ssl(ASYNC, OK);
5871 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075872 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5873 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:005874
5875 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5876 data_writes, arraysize(data_writes));
5877 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
5878 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:075879 session_deps_.socket_factory->AddSocketDataProvider(&data);
5880 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:005881
[email protected]49639fa2011-12-20 23:22:415882 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:005883
mmenke6b3af6e2015-09-12 02:06:065884 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:365885 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505886 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:005887
[email protected]49639fa2011-12-20 23:22:415888 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:005889
5890 EXPECT_EQ(ERR_IO_PENDING, rv);
5891 EXPECT_EQ(OK, callback.WaitForResult());
5892
5893 const HttpResponseInfo* response = trans->GetResponseInfo();
5894 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:505895 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:005896 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5897
[email protected]90499482013-06-01 00:39:505898 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:005899
5900 std::string response_data;
5901 rv = ReadTransaction(trans.get(), &response_data);
5902 EXPECT_EQ(OK, rv);
5903 EXPECT_EQ("hello world", response_data);
5904
5905 // Empty the current queue. This is necessary because idle sockets are
5906 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345907 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:005908
5909 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:505910 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:005911
5912 // Now start the second transaction, which should reuse the previous socket.
5913
[email protected]90499482013-06-01 00:39:505914 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:005915
[email protected]49639fa2011-12-20 23:22:415916 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:005917
5918 EXPECT_EQ(ERR_IO_PENDING, rv);
5919 EXPECT_EQ(OK, callback.WaitForResult());
5920
5921 response = trans->GetResponseInfo();
5922 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:505923 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:005924 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5925
[email protected]90499482013-06-01 00:39:505926 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:005927
5928 rv = ReadTransaction(trans.get(), &response_data);
5929 EXPECT_EQ(OK, rv);
5930 EXPECT_EQ("hello world", response_data);
5931
5932 // Empty the current queue. This is necessary because idle sockets are
5933 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345934 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:005935
5936 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:505937 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:005938}
5939
[email protected]b4404c02009-04-10 16:38:525940// Make sure that we recycle a socket after a zero-length response.
5941// http://crbug.com/9880
[email protected]23e482282013-06-14 16:08:025942TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:425943 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:525944 request.method = "GET";
bncce36dca22015-04-21 22:11:235945 request.url = GURL(
5946 "http://www.example.org/csi?v=3&s=web&action=&"
5947 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5948 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5949 "rt=prt.2642,ol.2649,xjs.2951");
[email protected]b4404c02009-04-10 16:38:525950 request.load_flags = 0;
5951
mmenke6b3af6e2015-09-12 02:06:065952 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275953
[email protected]262eec82013-03-19 21:01:365954 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505955 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:275956
[email protected]b4404c02009-04-10 16:38:525957 MockRead data_reads[] = {
5958 MockRead("HTTP/1.1 204 No Content\r\n"
5959 "Content-Length: 0\r\n"
5960 "Content-Type: text/html\r\n\r\n"),
5961 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:065962 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:525963 };
5964
[email protected]31a2bfe2010-02-09 08:03:395965 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:075966 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:525967
[email protected]49639fa2011-12-20 23:22:415968 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:525969
[email protected]49639fa2011-12-20 23:22:415970 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425971 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:525972
5973 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425974 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:525975
[email protected]1c773ea12009-04-28 19:58:425976 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505977 ASSERT_TRUE(response != NULL);
[email protected]b4404c02009-04-10 16:38:525978
[email protected]90499482013-06-01 00:39:505979 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]b4404c02009-04-10 16:38:525980 std::string status_line = response->headers->GetStatusLine();
5981 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
5982
[email protected]90499482013-06-01 00:39:505983 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:525984
5985 std::string response_data;
5986 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:425987 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:525988 EXPECT_EQ("", response_data);
5989
5990 // Empty the current queue. This is necessary because idle sockets are
5991 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345992 base::MessageLoop::current()->RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:525993
5994 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:505995 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:525996}
5997
[email protected]23e482282013-06-14 16:08:025998TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]b2d26cfd2012-12-11 10:36:065999 ScopedVector<UploadElementReader> element_readers;
6000 element_readers.push_back(new UploadBytesElementReader("foo", 3));
mmenkecbc2b712014-10-09 20:29:076001 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]329b68b2012-11-14 17:54:276002
[email protected]1c773ea12009-04-28 19:58:426003 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:516004 // Transaction 1: a GET request that succeeds. The socket is recycled
6005 // after use.
6006 request[0].method = "GET";
6007 request[0].url = GURL("http://www.google.com/");
6008 request[0].load_flags = 0;
6009 // Transaction 2: a POST request. Reuses the socket kept alive from
6010 // transaction 1. The first attempts fails when writing the POST data.
6011 // This causes the transaction to retry with a new socket. The second
6012 // attempt succeeds.
6013 request[1].method = "POST";
6014 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:276015 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:516016 request[1].load_flags = 0;
6017
mmenke6b3af6e2015-09-12 02:06:066018 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:516019
6020 // The first socket is used for transaction 1 and the first attempt of
6021 // transaction 2.
6022
6023 // The response of transaction 1.
6024 MockRead data_reads1[] = {
6025 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
6026 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066027 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:516028 };
6029 // The mock write results of transaction 1 and the first attempt of
6030 // transaction 2.
6031 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:066032 MockWrite(SYNCHRONOUS, 64), // GET
6033 MockWrite(SYNCHRONOUS, 93), // POST
6034 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:516035 };
[email protected]31a2bfe2010-02-09 08:03:396036 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6037 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:516038
6039 // The second socket is used for the second attempt of transaction 2.
6040
6041 // The response of transaction 2.
6042 MockRead data_reads2[] = {
6043 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
6044 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:066045 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:516046 };
6047 // The mock write results of the second attempt of transaction 2.
6048 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:066049 MockWrite(SYNCHRONOUS, 93), // POST
6050 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:516051 };
[email protected]31a2bfe2010-02-09 08:03:396052 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6053 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:516054
[email protected]bb88e1d32013-05-03 23:11:076055 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6056 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:516057
thestig9d3bb0c2015-01-24 00:49:516058 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:516059 "hello world", "welcome"
6060 };
6061
6062 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:426063 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506064 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]372d34a2008-11-05 21:30:516065
[email protected]49639fa2011-12-20 23:22:416066 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:516067
[email protected]49639fa2011-12-20 23:22:416068 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426069 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:516070
6071 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426072 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:516073
[email protected]1c773ea12009-04-28 19:58:426074 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506075 ASSERT_TRUE(response != NULL);
[email protected]372d34a2008-11-05 21:30:516076
[email protected]90499482013-06-01 00:39:506077 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]372d34a2008-11-05 21:30:516078 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6079
6080 std::string response_data;
6081 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:426082 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:516083 EXPECT_EQ(kExpectedResponseData[i], response_data);
6084 }
6085}
[email protected]f9ee6b52008-11-08 06:46:236086
6087// Test the request-challenge-retry sequence for basic auth when there is
6088// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:166089// it fails the identity from the URL is used to answer the challenge.
[email protected]23e482282013-06-14 16:08:026090TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:426091 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236092 request.method = "GET";
bncce36dca22015-04-21 22:11:236093 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:416094 request.load_flags = LOAD_NORMAL;
[email protected]a97cca42009-08-14 01:00:296095
mmenke6b3af6e2015-09-12 02:06:066096 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276097 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416098 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276099
[email protected]a97cca42009-08-14 01:00:296100 // The password contains an escaped character -- for this test to pass it
6101 // will need to be unescaped by HttpNetworkTransaction.
6102 EXPECT_EQ("b%40r", request.url.password());
6103
[email protected]f9ee6b52008-11-08 06:46:236104 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236105 MockWrite(
6106 "GET / HTTP/1.1\r\n"
6107 "Host: www.example.org\r\n"
6108 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236109 };
6110
6111 MockRead data_reads1[] = {
6112 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6113 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6114 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066115 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236116 };
6117
[email protected]2262e3a2012-05-22 16:08:166118 // After the challenge above, the transaction will be restarted using the
6119 // identity from the url (foo, b@r) to answer the challenge.
6120 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236121 MockWrite(
6122 "GET / HTTP/1.1\r\n"
6123 "Host: www.example.org\r\n"
6124 "Connection: keep-alive\r\n"
6125 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166126 };
6127
6128 MockRead data_reads2[] = {
6129 MockRead("HTTP/1.0 200 OK\r\n"),
6130 MockRead("Content-Length: 100\r\n\r\n"),
6131 MockRead(SYNCHRONOUS, OK),
6132 };
6133
[email protected]31a2bfe2010-02-09 08:03:396134 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6135 data_writes1, arraysize(data_writes1));
[email protected]2262e3a2012-05-22 16:08:166136 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6137 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076138 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6139 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236140
[email protected]49639fa2011-12-20 23:22:416141 TestCompletionCallback callback1;
[email protected]49639fa2011-12-20 23:22:416142 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426143 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236144 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426145 EXPECT_EQ(OK, rv);
[email protected]2262e3a2012-05-22 16:08:166146 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6147
6148 TestCompletionCallback callback2;
6149 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6150 EXPECT_EQ(ERR_IO_PENDING, rv);
6151 rv = callback2.WaitForResult();
6152 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226153 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6154
[email protected]2262e3a2012-05-22 16:08:166155 const HttpResponseInfo* response = trans->GetResponseInfo();
6156 ASSERT_TRUE(response != NULL);
6157
6158 // There is no challenge info, since the identity in URL worked.
6159 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6160
6161 EXPECT_EQ(100, response->headers->GetContentLength());
6162
6163 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:346164 base::MessageLoop::current()->RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:166165}
6166
6167// Test the request-challenge-retry sequence for basic auth when there is an
6168// incorrect identity in the URL. The identity from the URL should be used only
6169// once.
[email protected]23e482282013-06-14 16:08:026170TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:166171 HttpRequestInfo request;
6172 request.method = "GET";
6173 // Note: the URL has a username:password in it. The password "baz" is
6174 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:236175 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:166176
6177 request.load_flags = LOAD_NORMAL;
6178
mmenke6b3af6e2015-09-12 02:06:066179 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2262e3a2012-05-22 16:08:166180 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416181 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2262e3a2012-05-22 16:08:166182
6183 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236184 MockWrite(
6185 "GET / HTTP/1.1\r\n"
6186 "Host: www.example.org\r\n"
6187 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166188 };
6189
6190 MockRead data_reads1[] = {
6191 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6192 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6193 MockRead("Content-Length: 10\r\n\r\n"),
6194 MockRead(SYNCHRONOUS, ERR_FAILED),
6195 };
6196
6197 // After the challenge above, the transaction will be restarted using the
6198 // identity from the url (foo, baz) to answer the challenge.
6199 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236200 MockWrite(
6201 "GET / HTTP/1.1\r\n"
6202 "Host: www.example.org\r\n"
6203 "Connection: keep-alive\r\n"
6204 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166205 };
6206
6207 MockRead data_reads2[] = {
6208 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6209 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6210 MockRead("Content-Length: 10\r\n\r\n"),
6211 MockRead(SYNCHRONOUS, ERR_FAILED),
6212 };
6213
6214 // After the challenge above, the transaction will be restarted using the
6215 // identity supplied by the user (foo, bar) to answer the challenge.
6216 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236217 MockWrite(
6218 "GET / HTTP/1.1\r\n"
6219 "Host: www.example.org\r\n"
6220 "Connection: keep-alive\r\n"
6221 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166222 };
6223
6224 MockRead data_reads3[] = {
6225 MockRead("HTTP/1.0 200 OK\r\n"),
6226 MockRead("Content-Length: 100\r\n\r\n"),
6227 MockRead(SYNCHRONOUS, OK),
6228 };
6229
6230 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6231 data_writes1, arraysize(data_writes1));
6232 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6233 data_writes2, arraysize(data_writes2));
6234 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6235 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:076236 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6237 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6238 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:166239
6240 TestCompletionCallback callback1;
6241
6242 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6243 EXPECT_EQ(ERR_IO_PENDING, rv);
6244
6245 rv = callback1.WaitForResult();
6246 EXPECT_EQ(OK, rv);
6247
6248 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6249 TestCompletionCallback callback2;
6250 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6251 EXPECT_EQ(ERR_IO_PENDING, rv);
6252 rv = callback2.WaitForResult();
6253 EXPECT_EQ(OK, rv);
6254 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6255
6256 const HttpResponseInfo* response = trans->GetResponseInfo();
6257 ASSERT_TRUE(response != NULL);
6258 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6259
6260 TestCompletionCallback callback3;
6261 rv = trans->RestartWithAuth(
6262 AuthCredentials(kFoo, kBar), callback3.callback());
6263 EXPECT_EQ(ERR_IO_PENDING, rv);
6264 rv = callback3.WaitForResult();
6265 EXPECT_EQ(OK, rv);
6266 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6267
6268 response = trans->GetResponseInfo();
6269 ASSERT_TRUE(response != NULL);
6270
6271 // There is no challenge info, since the identity worked.
6272 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6273
6274 EXPECT_EQ(100, response->headers->GetContentLength());
6275
[email protected]ea9dc9a2009-09-05 00:43:326276 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:346277 base::MessageLoop::current()->RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:326278}
6279
[email protected]2217aa22013-10-11 03:03:546280
6281// Test the request-challenge-retry sequence for basic auth when there is a
6282// correct identity in the URL, but its use is being suppressed. The identity
6283// from the URL should never be used.
6284TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
6285 HttpRequestInfo request;
6286 request.method = "GET";
bncce36dca22015-04-21 22:11:236287 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:546288 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
6289
mmenke6b3af6e2015-09-12 02:06:066290 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2217aa22013-10-11 03:03:546291 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416292 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2217aa22013-10-11 03:03:546293
6294 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236295 MockWrite(
6296 "GET / HTTP/1.1\r\n"
6297 "Host: www.example.org\r\n"
6298 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:546299 };
6300
6301 MockRead data_reads1[] = {
6302 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6303 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6304 MockRead("Content-Length: 10\r\n\r\n"),
6305 MockRead(SYNCHRONOUS, ERR_FAILED),
6306 };
6307
6308 // After the challenge above, the transaction will be restarted using the
6309 // identity supplied by the user, not the one in the URL, to answer the
6310 // challenge.
6311 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236312 MockWrite(
6313 "GET / HTTP/1.1\r\n"
6314 "Host: www.example.org\r\n"
6315 "Connection: keep-alive\r\n"
6316 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:546317 };
6318
6319 MockRead data_reads3[] = {
6320 MockRead("HTTP/1.0 200 OK\r\n"),
6321 MockRead("Content-Length: 100\r\n\r\n"),
6322 MockRead(SYNCHRONOUS, OK),
6323 };
6324
6325 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6326 data_writes1, arraysize(data_writes1));
6327 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6328 data_writes3, arraysize(data_writes3));
6329 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6330 session_deps_.socket_factory->AddSocketDataProvider(&data3);
6331
6332 TestCompletionCallback callback1;
6333 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6334 EXPECT_EQ(ERR_IO_PENDING, rv);
6335 rv = callback1.WaitForResult();
6336 EXPECT_EQ(OK, rv);
6337 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6338
6339 const HttpResponseInfo* response = trans->GetResponseInfo();
6340 ASSERT_TRUE(response != NULL);
6341 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6342
6343 TestCompletionCallback callback3;
6344 rv = trans->RestartWithAuth(
6345 AuthCredentials(kFoo, kBar), callback3.callback());
6346 EXPECT_EQ(ERR_IO_PENDING, rv);
6347 rv = callback3.WaitForResult();
6348 EXPECT_EQ(OK, rv);
6349 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6350
6351 response = trans->GetResponseInfo();
6352 ASSERT_TRUE(response != NULL);
6353
6354 // There is no challenge info, since the identity worked.
6355 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6356 EXPECT_EQ(100, response->headers->GetContentLength());
6357
6358 // Empty the current queue.
6359 base::MessageLoop::current()->RunUntilIdle();
6360}
6361
[email protected]f9ee6b52008-11-08 06:46:236362// Test that previously tried username/passwords for a realm get re-used.
[email protected]23e482282013-06-14 16:08:026363TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
mmenke6b3af6e2015-09-12 02:06:066364 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:236365
6366 // Transaction 1: authenticate (foo, bar) on MyRealm1
6367 {
[email protected]1c773ea12009-04-28 19:58:426368 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236369 request.method = "GET";
bncce36dca22015-04-21 22:11:236370 request.url = GURL("http://www.example.org/x/y/z");
[email protected]f9ee6b52008-11-08 06:46:236371 request.load_flags = 0;
6372
[email protected]262eec82013-03-19 21:01:366373 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506374 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276375
[email protected]f9ee6b52008-11-08 06:46:236376 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236377 MockWrite(
6378 "GET /x/y/z HTTP/1.1\r\n"
6379 "Host: www.example.org\r\n"
6380 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236381 };
6382
6383 MockRead data_reads1[] = {
6384 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6385 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6386 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066387 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236388 };
6389
6390 // Resend with authorization (username=foo, password=bar)
6391 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236392 MockWrite(
6393 "GET /x/y/z HTTP/1.1\r\n"
6394 "Host: www.example.org\r\n"
6395 "Connection: keep-alive\r\n"
6396 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236397 };
6398
6399 // Sever accepts the authorization.
6400 MockRead data_reads2[] = {
6401 MockRead("HTTP/1.0 200 OK\r\n"),
6402 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066403 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236404 };
6405
[email protected]31a2bfe2010-02-09 08:03:396406 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6407 data_writes1, arraysize(data_writes1));
6408 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6409 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076410 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6411 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236412
[email protected]49639fa2011-12-20 23:22:416413 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236414
[email protected]49639fa2011-12-20 23:22:416415 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426416 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236417
6418 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426419 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236420
[email protected]1c773ea12009-04-28 19:58:426421 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506422 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046423 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:236424
[email protected]49639fa2011-12-20 23:22:416425 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:236426
[email protected]49639fa2011-12-20 23:22:416427 rv = trans->RestartWithAuth(
6428 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426429 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236430
6431 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426432 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236433
6434 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506435 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236436 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6437 EXPECT_EQ(100, response->headers->GetContentLength());
6438 }
6439
6440 // ------------------------------------------------------------------------
6441
6442 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
6443 {
[email protected]1c773ea12009-04-28 19:58:426444 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236445 request.method = "GET";
6446 // Note that Transaction 1 was at /x/y/z, so this is in the same
6447 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:236448 request.url = GURL("http://www.example.org/x/y/a/b");
[email protected]f9ee6b52008-11-08 06:46:236449 request.load_flags = 0;
6450
[email protected]262eec82013-03-19 21:01:366451 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506452 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276453
[email protected]f9ee6b52008-11-08 06:46:236454 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236455 MockWrite(
6456 "GET /x/y/a/b HTTP/1.1\r\n"
6457 "Host: www.example.org\r\n"
6458 "Connection: keep-alive\r\n"
6459 // Send preemptive authorization for MyRealm1
6460 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236461 };
6462
6463 // The server didn't like the preemptive authorization, and
6464 // challenges us for a different realm (MyRealm2).
6465 MockRead data_reads1[] = {
6466 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6467 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
6468 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066469 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236470 };
6471
6472 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
6473 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236474 MockWrite(
6475 "GET /x/y/a/b HTTP/1.1\r\n"
6476 "Host: www.example.org\r\n"
6477 "Connection: keep-alive\r\n"
6478 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236479 };
6480
6481 // Sever accepts the authorization.
6482 MockRead data_reads2[] = {
6483 MockRead("HTTP/1.0 200 OK\r\n"),
6484 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066485 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236486 };
6487
[email protected]31a2bfe2010-02-09 08:03:396488 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6489 data_writes1, arraysize(data_writes1));
6490 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6491 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076492 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6493 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236494
[email protected]49639fa2011-12-20 23:22:416495 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236496
[email protected]49639fa2011-12-20 23:22:416497 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426498 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236499
6500 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426501 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236502
[email protected]1c773ea12009-04-28 19:58:426503 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506504 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046505 ASSERT_TRUE(response->auth_challenge.get());
6506 EXPECT_FALSE(response->auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:236507 EXPECT_EQ("www.example.org:80",
[email protected]79cb5c12011-09-12 13:12:046508 response->auth_challenge->challenger.ToString());
6509 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
6510 EXPECT_EQ("basic", response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:236511
[email protected]49639fa2011-12-20 23:22:416512 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:236513
[email protected]49639fa2011-12-20 23:22:416514 rv = trans->RestartWithAuth(
6515 AuthCredentials(kFoo2, kBar2), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426516 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236517
6518 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426519 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236520
6521 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506522 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236523 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6524 EXPECT_EQ(100, response->headers->GetContentLength());
6525 }
6526
6527 // ------------------------------------------------------------------------
6528
6529 // Transaction 3: Resend a request in MyRealm's protection space --
6530 // succeed with preemptive authorization.
6531 {
[email protected]1c773ea12009-04-28 19:58:426532 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236533 request.method = "GET";
bncce36dca22015-04-21 22:11:236534 request.url = GURL("http://www.example.org/x/y/z2");
[email protected]f9ee6b52008-11-08 06:46:236535 request.load_flags = 0;
6536
[email protected]262eec82013-03-19 21:01:366537 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506538 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276539
[email protected]f9ee6b52008-11-08 06:46:236540 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236541 MockWrite(
6542 "GET /x/y/z2 HTTP/1.1\r\n"
6543 "Host: www.example.org\r\n"
6544 "Connection: keep-alive\r\n"
6545 // The authorization for MyRealm1 gets sent preemptively
6546 // (since the url is in the same protection space)
6547 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236548 };
6549
6550 // Sever accepts the preemptive authorization
6551 MockRead data_reads1[] = {
6552 MockRead("HTTP/1.0 200 OK\r\n"),
6553 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066554 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236555 };
6556
[email protected]31a2bfe2010-02-09 08:03:396557 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6558 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:076559 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:236560
[email protected]49639fa2011-12-20 23:22:416561 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236562
[email protected]49639fa2011-12-20 23:22:416563 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426564 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236565
6566 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426567 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236568
[email protected]1c773ea12009-04-28 19:58:426569 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506570 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236571
6572 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6573 EXPECT_EQ(100, response->headers->GetContentLength());
6574 }
6575
6576 // ------------------------------------------------------------------------
6577
6578 // Transaction 4: request another URL in MyRealm (however the
6579 // url is not known to belong to the protection space, so no pre-auth).
6580 {
[email protected]1c773ea12009-04-28 19:58:426581 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236582 request.method = "GET";
bncce36dca22015-04-21 22:11:236583 request.url = GURL("http://www.example.org/x/1");
[email protected]f9ee6b52008-11-08 06:46:236584 request.load_flags = 0;
6585
[email protected]262eec82013-03-19 21:01:366586 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506587 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276588
[email protected]f9ee6b52008-11-08 06:46:236589 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236590 MockWrite(
6591 "GET /x/1 HTTP/1.1\r\n"
6592 "Host: www.example.org\r\n"
6593 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236594 };
6595
6596 MockRead data_reads1[] = {
6597 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6598 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6599 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066600 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236601 };
6602
6603 // Resend with authorization from MyRealm's cache.
6604 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236605 MockWrite(
6606 "GET /x/1 HTTP/1.1\r\n"
6607 "Host: www.example.org\r\n"
6608 "Connection: keep-alive\r\n"
6609 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236610 };
6611
6612 // Sever accepts the authorization.
6613 MockRead data_reads2[] = {
6614 MockRead("HTTP/1.0 200 OK\r\n"),
6615 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066616 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236617 };
6618
[email protected]31a2bfe2010-02-09 08:03:396619 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6620 data_writes1, arraysize(data_writes1));
6621 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6622 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076623 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6624 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236625
[email protected]49639fa2011-12-20 23:22:416626 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236627
[email protected]49639fa2011-12-20 23:22:416628 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426629 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236630
6631 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426632 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236633
[email protected]0757e7702009-03-27 04:00:226634 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:416635 TestCompletionCallback callback2;
6636 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426637 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:226638 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426639 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226640 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6641
[email protected]1c773ea12009-04-28 19:58:426642 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506643 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236644 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6645 EXPECT_EQ(100, response->headers->GetContentLength());
6646 }
6647
6648 // ------------------------------------------------------------------------
6649
6650 // Transaction 5: request a URL in MyRealm, but the server rejects the
6651 // cached identity. Should invalidate and re-prompt.
6652 {
[email protected]1c773ea12009-04-28 19:58:426653 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236654 request.method = "GET";
bncce36dca22015-04-21 22:11:236655 request.url = GURL("http://www.example.org/p/q/t");
[email protected]f9ee6b52008-11-08 06:46:236656 request.load_flags = 0;
6657
[email protected]262eec82013-03-19 21:01:366658 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506659 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276660
[email protected]f9ee6b52008-11-08 06:46:236661 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236662 MockWrite(
6663 "GET /p/q/t HTTP/1.1\r\n"
6664 "Host: www.example.org\r\n"
6665 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236666 };
6667
6668 MockRead data_reads1[] = {
6669 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6670 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6671 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066672 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236673 };
6674
6675 // Resend with authorization from cache for MyRealm.
6676 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236677 MockWrite(
6678 "GET /p/q/t HTTP/1.1\r\n"
6679 "Host: www.example.org\r\n"
6680 "Connection: keep-alive\r\n"
6681 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236682 };
6683
6684 // Sever rejects the authorization.
6685 MockRead data_reads2[] = {
6686 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6687 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6688 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066689 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236690 };
6691
6692 // At this point we should prompt for new credentials for MyRealm.
6693 // Restart with username=foo3, password=foo4.
6694 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236695 MockWrite(
6696 "GET /p/q/t HTTP/1.1\r\n"
6697 "Host: www.example.org\r\n"
6698 "Connection: keep-alive\r\n"
6699 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236700 };
6701
6702 // Sever accepts the authorization.
6703 MockRead data_reads3[] = {
6704 MockRead("HTTP/1.0 200 OK\r\n"),
6705 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066706 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236707 };
6708
[email protected]31a2bfe2010-02-09 08:03:396709 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6710 data_writes1, arraysize(data_writes1));
6711 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6712 data_writes2, arraysize(data_writes2));
6713 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6714 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:076715 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6716 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6717 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:236718
[email protected]49639fa2011-12-20 23:22:416719 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236720
[email protected]49639fa2011-12-20 23:22:416721 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426722 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236723
6724 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426725 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236726
[email protected]0757e7702009-03-27 04:00:226727 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:416728 TestCompletionCallback callback2;
6729 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426730 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:226731 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426732 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226733 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6734
[email protected]1c773ea12009-04-28 19:58:426735 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506736 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046737 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:236738
[email protected]49639fa2011-12-20 23:22:416739 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:236740
[email protected]49639fa2011-12-20 23:22:416741 rv = trans->RestartWithAuth(
6742 AuthCredentials(kFoo3, kBar3), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:426743 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236744
[email protected]0757e7702009-03-27 04:00:226745 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426746 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236747
6748 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506749 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236750 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6751 EXPECT_EQ(100, response->headers->GetContentLength());
6752 }
6753}
[email protected]89ceba9a2009-03-21 03:46:066754
[email protected]3c32c5f2010-05-18 15:18:126755// Tests that nonce count increments when multiple auth attempts
6756// are started with the same nonce.
[email protected]23e482282013-06-14 16:08:026757TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:446758 HttpAuthHandlerDigest::Factory* digest_factory =
6759 new HttpAuthHandlerDigest::Factory();
6760 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
6761 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6762 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:076763 session_deps_.http_auth_handler_factory.reset(digest_factory);
mmenke6b3af6e2015-09-12 02:06:066764 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:126765
6766 // Transaction 1: authenticate (foo, bar) on MyRealm1
6767 {
[email protected]3c32c5f2010-05-18 15:18:126768 HttpRequestInfo request;
6769 request.method = "GET";
bncce36dca22015-04-21 22:11:236770 request.url = GURL("http://www.example.org/x/y/z");
[email protected]3c32c5f2010-05-18 15:18:126771 request.load_flags = 0;
6772
[email protected]262eec82013-03-19 21:01:366773 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506774 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276775
[email protected]3c32c5f2010-05-18 15:18:126776 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236777 MockWrite(
6778 "GET /x/y/z HTTP/1.1\r\n"
6779 "Host: www.example.org\r\n"
6780 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:126781 };
6782
6783 MockRead data_reads1[] = {
6784 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6785 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6786 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066787 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:126788 };
6789
6790 // Resend with authorization (username=foo, password=bar)
6791 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236792 MockWrite(
6793 "GET /x/y/z HTTP/1.1\r\n"
6794 "Host: www.example.org\r\n"
6795 "Connection: keep-alive\r\n"
6796 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6797 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6798 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6799 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:126800 };
6801
6802 // Sever accepts the authorization.
6803 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:086804 MockRead("HTTP/1.0 200 OK\r\n"),
6805 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:126806 };
6807
6808 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6809 data_writes1, arraysize(data_writes1));
6810 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6811 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076812 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6813 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:126814
[email protected]49639fa2011-12-20 23:22:416815 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:126816
[email protected]49639fa2011-12-20 23:22:416817 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:126818 EXPECT_EQ(ERR_IO_PENDING, rv);
6819
6820 rv = callback1.WaitForResult();
6821 EXPECT_EQ(OK, rv);
6822
6823 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506824 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046825 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
[email protected]3c32c5f2010-05-18 15:18:126826
[email protected]49639fa2011-12-20 23:22:416827 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:126828
[email protected]49639fa2011-12-20 23:22:416829 rv = trans->RestartWithAuth(
6830 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]3c32c5f2010-05-18 15:18:126831 EXPECT_EQ(ERR_IO_PENDING, rv);
6832
6833 rv = callback2.WaitForResult();
6834 EXPECT_EQ(OK, rv);
6835
6836 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506837 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:126838 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6839 }
6840
6841 // ------------------------------------------------------------------------
6842
6843 // Transaction 2: Request another resource in digestive's protection space.
6844 // This will preemptively add an Authorization header which should have an
6845 // "nc" value of 2 (as compared to 1 in the first use.
6846 {
[email protected]3c32c5f2010-05-18 15:18:126847 HttpRequestInfo request;
6848 request.method = "GET";
6849 // Note that Transaction 1 was at /x/y/z, so this is in the same
6850 // protection space as digest.
bncce36dca22015-04-21 22:11:236851 request.url = GURL("http://www.example.org/x/y/a/b");
[email protected]3c32c5f2010-05-18 15:18:126852 request.load_flags = 0;
6853
[email protected]262eec82013-03-19 21:01:366854 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506855 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276856
[email protected]3c32c5f2010-05-18 15:18:126857 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236858 MockWrite(
6859 "GET /x/y/a/b HTTP/1.1\r\n"
6860 "Host: www.example.org\r\n"
6861 "Connection: keep-alive\r\n"
6862 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6863 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6864 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6865 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:126866 };
6867
6868 // Sever accepts the authorization.
6869 MockRead data_reads1[] = {
6870 MockRead("HTTP/1.0 200 OK\r\n"),
6871 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066872 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:126873 };
6874
6875 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6876 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:076877 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:126878
[email protected]49639fa2011-12-20 23:22:416879 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:126880
[email protected]49639fa2011-12-20 23:22:416881 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:126882 EXPECT_EQ(ERR_IO_PENDING, rv);
6883
6884 rv = callback1.WaitForResult();
6885 EXPECT_EQ(OK, rv);
6886
6887 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506888 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:126889 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6890 }
6891}
6892
[email protected]89ceba9a2009-03-21 03:46:066893// Test the ResetStateForRestart() private method.
[email protected]23e482282013-06-14 16:08:026894TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:066895 // Create a transaction (the dependencies aren't important).
mmenke6b3af6e2015-09-12 02:06:066896 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:406897 scoped_ptr<HttpNetworkTransaction> trans(
dcheng48459ac22014-08-26 00:46:416898 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]89ceba9a2009-03-21 03:46:066899
6900 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:066901 trans->read_buf_ = new IOBuffer(15);
6902 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:206903 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:066904
6905 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:146906 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:576907 response->auth_challenge = new AuthChallengeInfo();
[email protected]70d66502011-09-23 00:55:086908 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:576909 response->response_time = base::Time::Now();
6910 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:066911
6912 { // Setup state for response_.vary_data
6913 HttpRequestInfo request;
6914 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6915 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:276916 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:436917 request.extra_headers.SetHeader("Foo", "1");
6918 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:506919 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:066920 }
6921
6922 // Cause the above state to be reset.
6923 trans->ResetStateForRestart();
6924
6925 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:076926 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:066927 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:206928 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:576929 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6930 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:046931 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:086932 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:576933 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:066934}
6935
[email protected]bacff652009-03-31 17:50:336936// Test HTTPS connections to a site with a bad certificate
[email protected]23e482282013-06-14 16:08:026937TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:336938 HttpRequestInfo request;
6939 request.method = "GET";
bncce36dca22015-04-21 22:11:236940 request.url = GURL("https://www.example.org/");
[email protected]bacff652009-03-31 17:50:336941 request.load_flags = 0;
6942
mmenke6b3af6e2015-09-12 02:06:066943 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276944 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416945 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276946
[email protected]bacff652009-03-31 17:50:336947 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:236948 MockWrite(
6949 "GET / HTTP/1.1\r\n"
6950 "Host: www.example.org\r\n"
6951 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:336952 };
6953
6954 MockRead data_reads[] = {
6955 MockRead("HTTP/1.0 200 OK\r\n"),
6956 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6957 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066958 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:336959 };
6960
[email protected]5ecc992a42009-11-11 01:41:596961 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:396962 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6963 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:066964 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6965 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:336966
[email protected]bb88e1d32013-05-03 23:11:076967 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6968 session_deps_.socket_factory->AddSocketDataProvider(&data);
6969 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6970 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:336971
[email protected]49639fa2011-12-20 23:22:416972 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:336973
[email protected]49639fa2011-12-20 23:22:416974 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:336975 EXPECT_EQ(ERR_IO_PENDING, rv);
6976
6977 rv = callback.WaitForResult();
6978 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6979
[email protected]49639fa2011-12-20 23:22:416980 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:336981 EXPECT_EQ(ERR_IO_PENDING, rv);
6982
6983 rv = callback.WaitForResult();
6984 EXPECT_EQ(OK, rv);
6985
6986 const HttpResponseInfo* response = trans->GetResponseInfo();
6987
[email protected]fe2255a2011-09-20 19:37:506988 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:336989 EXPECT_EQ(100, response->headers->GetContentLength());
6990}
6991
6992// Test HTTPS connections to a site with a bad certificate, going through a
6993// proxy
[email protected]23e482282013-06-14 16:08:026994TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
rdsmith82957ad2015-09-16 19:42:036995 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]bacff652009-03-31 17:50:336996
6997 HttpRequestInfo request;
6998 request.method = "GET";
bncce36dca22015-04-21 22:11:236999 request.url = GURL("https://www.example.org/");
[email protected]bacff652009-03-31 17:50:337000 request.load_flags = 0;
7001
7002 MockWrite proxy_writes[] = {
bncce36dca22015-04-21 22:11:237003 MockWrite(
7004 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7005 "Host: www.example.org\r\n"
7006 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337007 };
7008
7009 MockRead proxy_reads[] = {
7010 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067011 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:337012 };
7013
7014 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237015 MockWrite(
7016 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7017 "Host: www.example.org\r\n"
7018 "Proxy-Connection: keep-alive\r\n\r\n"),
7019 MockWrite(
7020 "GET / HTTP/1.1\r\n"
7021 "Host: www.example.org\r\n"
7022 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337023 };
7024
7025 MockRead data_reads[] = {
7026 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7027 MockRead("HTTP/1.0 200 OK\r\n"),
7028 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7029 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067030 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:337031 };
7032
[email protected]31a2bfe2010-02-09 08:03:397033 StaticSocketDataProvider ssl_bad_certificate(
7034 proxy_reads, arraysize(proxy_reads),
7035 proxy_writes, arraysize(proxy_writes));
7036 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7037 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067038 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7039 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:337040
[email protected]bb88e1d32013-05-03 23:11:077041 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7042 session_deps_.socket_factory->AddSocketDataProvider(&data);
7043 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7044 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:337045
[email protected]49639fa2011-12-20 23:22:417046 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:337047
7048 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:077049 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:337050
mmenke6b3af6e2015-09-12 02:06:067051 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:407052 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417053 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bacff652009-03-31 17:50:337054
[email protected]49639fa2011-12-20 23:22:417055 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:337056 EXPECT_EQ(ERR_IO_PENDING, rv);
7057
7058 rv = callback.WaitForResult();
7059 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7060
[email protected]49639fa2011-12-20 23:22:417061 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:337062 EXPECT_EQ(ERR_IO_PENDING, rv);
7063
7064 rv = callback.WaitForResult();
7065 EXPECT_EQ(OK, rv);
7066
7067 const HttpResponseInfo* response = trans->GetResponseInfo();
7068
[email protected]fe2255a2011-09-20 19:37:507069 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:337070 EXPECT_EQ(100, response->headers->GetContentLength());
7071 }
7072}
7073
[email protected]2df19bb2010-08-25 20:13:467074
7075// Test HTTPS connections to a site, going through an HTTPS proxy
[email protected]23e482282013-06-14 16:08:027076TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037077 session_deps_.proxy_service =
7078 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:517079 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:077080 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:467081
7082 HttpRequestInfo request;
7083 request.method = "GET";
bncce36dca22015-04-21 22:11:237084 request.url = GURL("https://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467085 request.load_flags = 0;
7086
7087 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237088 MockWrite(
7089 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7090 "Host: www.example.org\r\n"
7091 "Proxy-Connection: keep-alive\r\n\r\n"),
7092 MockWrite(
7093 "GET / HTTP/1.1\r\n"
7094 "Host: www.example.org\r\n"
7095 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467096 };
7097
7098 MockRead data_reads[] = {
7099 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7100 MockRead("HTTP/1.1 200 OK\r\n"),
7101 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7102 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067103 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467104 };
7105
7106 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7107 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067108 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
7109 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:467110
[email protected]bb88e1d32013-05-03 23:11:077111 session_deps_.socket_factory->AddSocketDataProvider(&data);
7112 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
7113 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:467114
[email protected]49639fa2011-12-20 23:22:417115 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:467116
mmenke6b3af6e2015-09-12 02:06:067117 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:467118 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417119 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2df19bb2010-08-25 20:13:467120
[email protected]49639fa2011-12-20 23:22:417121 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:467122 EXPECT_EQ(ERR_IO_PENDING, rv);
7123
7124 rv = callback.WaitForResult();
7125 EXPECT_EQ(OK, rv);
7126 const HttpResponseInfo* response = trans->GetResponseInfo();
7127
[email protected]fe2255a2011-09-20 19:37:507128 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:467129
7130 EXPECT_TRUE(response->headers->IsKeepAlive());
7131 EXPECT_EQ(200, response->headers->response_code());
7132 EXPECT_EQ(100, response->headers->GetContentLength());
7133 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:207134
7135 LoadTimingInfo load_timing_info;
7136 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7137 TestLoadTimingNotReusedWithPac(load_timing_info,
7138 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:467139}
7140
[email protected]511f6f52010-12-17 03:58:297141// Test an HTTPS Proxy's ability to redirect a CONNECT request
[email protected]23e482282013-06-14 16:08:027142TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037143 session_deps_.proxy_service =
7144 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:517145 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:077146 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:297147
7148 HttpRequestInfo request;
7149 request.method = "GET";
bncce36dca22015-04-21 22:11:237150 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297151 request.load_flags = 0;
7152
7153 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237154 MockWrite(
7155 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7156 "Host: www.example.org\r\n"
7157 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:297158 };
7159
7160 MockRead data_reads[] = {
7161 MockRead("HTTP/1.1 302 Redirect\r\n"),
7162 MockRead("Location: http://login.example.com/\r\n"),
7163 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067164 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:297165 };
7166
7167 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7168 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067169 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:297170
[email protected]bb88e1d32013-05-03 23:11:077171 session_deps_.socket_factory->AddSocketDataProvider(&data);
7172 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297173
[email protected]49639fa2011-12-20 23:22:417174 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297175
mmenke6b3af6e2015-09-12 02:06:067176 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297177 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417178 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297179
[email protected]49639fa2011-12-20 23:22:417180 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297181 EXPECT_EQ(ERR_IO_PENDING, rv);
7182
7183 rv = callback.WaitForResult();
7184 EXPECT_EQ(OK, rv);
7185 const HttpResponseInfo* response = trans->GetResponseInfo();
7186
[email protected]fe2255a2011-09-20 19:37:507187 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:297188
7189 EXPECT_EQ(302, response->headers->response_code());
7190 std::string url;
7191 EXPECT_TRUE(response->headers->IsRedirect(&url));
7192 EXPECT_EQ("http://login.example.com/", url);
[email protected]029c83b62013-01-24 05:28:207193
7194 // In the case of redirects from proxies, HttpNetworkTransaction returns
7195 // timing for the proxy connection instead of the connection to the host,
7196 // and no send / receive times.
7197 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
7198 LoadTimingInfo load_timing_info;
7199 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7200
7201 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:297202 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:207203
7204 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
7205 EXPECT_LE(load_timing_info.proxy_resolve_start,
7206 load_timing_info.proxy_resolve_end);
7207 EXPECT_LE(load_timing_info.proxy_resolve_end,
7208 load_timing_info.connect_timing.connect_start);
7209 ExpectConnectTimingHasTimes(
7210 load_timing_info.connect_timing,
7211 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
7212
7213 EXPECT_TRUE(load_timing_info.send_start.is_null());
7214 EXPECT_TRUE(load_timing_info.send_end.is_null());
7215 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]511f6f52010-12-17 03:58:297216}
7217
7218// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
[email protected]23e482282013-06-14 16:08:027219TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
rdsmith82957ad2015-09-16 19:42:037220 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297221
7222 HttpRequestInfo request;
7223 request.method = "GET";
bncce36dca22015-04-21 22:11:237224 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297225 request.load_flags = 0;
7226
lgarrona91df87f2014-12-05 00:51:347227 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237228 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207229 scoped_ptr<SpdyFrame> goaway(
7230 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]511f6f52010-12-17 03:58:297231 MockWrite data_writes[] = {
rch8e6c6c42015-05-01 14:05:137232 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
7233 CreateMockWrite(*goaway.get(), 2, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:297234 };
7235
7236 static const char* const kExtraHeaders[] = {
7237 "location",
7238 "http://login.example.com/",
7239 };
[email protected]ff98d7f02012-03-22 21:44:197240 scoped_ptr<SpdyFrame> resp(
[email protected]23e482282013-06-14 16:08:027241 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
[email protected]511f6f52010-12-17 03:58:297242 arraysize(kExtraHeaders)/2, 1));
7243 MockRead data_reads[] = {
rch8e6c6c42015-05-01 14:05:137244 CreateMockRead(*resp.get(), 1), MockRead(ASYNC, 0, 3), // EOF
[email protected]511f6f52010-12-17 03:58:297245 };
7246
rch8e6c6c42015-05-01 14:05:137247 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
7248 arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067249 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]23e482282013-06-14 16:08:027250 proxy_ssl.SetNextProto(GetParam());
[email protected]511f6f52010-12-17 03:58:297251
[email protected]bb88e1d32013-05-03 23:11:077252 session_deps_.socket_factory->AddSocketDataProvider(&data);
7253 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297254
[email protected]49639fa2011-12-20 23:22:417255 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297256
mmenke6b3af6e2015-09-12 02:06:067257 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297258 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417259 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297260
[email protected]49639fa2011-12-20 23:22:417261 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297262 EXPECT_EQ(ERR_IO_PENDING, rv);
7263
7264 rv = callback.WaitForResult();
7265 EXPECT_EQ(OK, rv);
7266 const HttpResponseInfo* response = trans->GetResponseInfo();
7267
[email protected]fe2255a2011-09-20 19:37:507268 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:297269
7270 EXPECT_EQ(302, response->headers->response_code());
7271 std::string url;
7272 EXPECT_TRUE(response->headers->IsRedirect(&url));
7273 EXPECT_EQ("http://login.example.com/", url);
7274}
7275
[email protected]4eddbc732012-08-09 05:40:177276// Test that an HTTPS proxy's response to a CONNECT request is filtered.
[email protected]23e482282013-06-14 16:08:027277TEST_P(HttpNetworkTransactionTest,
[email protected]4eddbc732012-08-09 05:40:177278 ErrorResponseToHttpsConnectViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037279 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297280
7281 HttpRequestInfo request;
7282 request.method = "GET";
bncce36dca22015-04-21 22:11:237283 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297284 request.load_flags = 0;
7285
7286 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237287 MockWrite(
7288 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7289 "Host: www.example.org\r\n"
7290 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:297291 };
7292
7293 MockRead data_reads[] = {
7294 MockRead("HTTP/1.1 404 Not Found\r\n"),
7295 MockRead("Content-Length: 23\r\n\r\n"),
7296 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:067297 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:297298 };
7299
7300 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7301 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067302 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:297303
[email protected]bb88e1d32013-05-03 23:11:077304 session_deps_.socket_factory->AddSocketDataProvider(&data);
7305 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297306
[email protected]49639fa2011-12-20 23:22:417307 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297308
mmenke6b3af6e2015-09-12 02:06:067309 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297310 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417311 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297312
[email protected]49639fa2011-12-20 23:22:417313 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297314 EXPECT_EQ(ERR_IO_PENDING, rv);
7315
7316 rv = callback.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:177317 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]511f6f52010-12-17 03:58:297318
[email protected]4eddbc732012-08-09 05:40:177319 // TODO(ttuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:297320}
7321
[email protected]4eddbc732012-08-09 05:40:177322// Test that a SPDY proxy's response to a CONNECT request is filtered.
[email protected]23e482282013-06-14 16:08:027323TEST_P(HttpNetworkTransactionTest,
[email protected]4eddbc732012-08-09 05:40:177324 ErrorResponseToHttpsConnectViaSpdyProxy) {
rdsmith82957ad2015-09-16 19:42:037325 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297326
7327 HttpRequestInfo request;
7328 request.method = "GET";
bncce36dca22015-04-21 22:11:237329 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297330 request.load_flags = 0;
7331
lgarrona91df87f2014-12-05 00:51:347332 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237333 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207334 scoped_ptr<SpdyFrame> rst(
7335 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]511f6f52010-12-17 03:58:297336 MockWrite data_writes[] = {
rch8e6c6c42015-05-01 14:05:137337 CreateMockWrite(*conn.get(), 0), CreateMockWrite(*rst.get(), 3),
[email protected]511f6f52010-12-17 03:58:297338 };
7339
7340 static const char* const kExtraHeaders[] = {
7341 "location",
7342 "http://login.example.com/",
7343 };
[email protected]ff98d7f02012-03-22 21:44:197344 scoped_ptr<SpdyFrame> resp(
[email protected]23e482282013-06-14 16:08:027345 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
[email protected]511f6f52010-12-17 03:58:297346 arraysize(kExtraHeaders)/2, 1));
[email protected]ff98d7f02012-03-22 21:44:197347 scoped_ptr<SpdyFrame> body(
[email protected]23e482282013-06-14 16:08:027348 spdy_util_.ConstructSpdyBodyFrame(
7349 1, "The host does not exist", 23, true));
[email protected]511f6f52010-12-17 03:58:297350 MockRead data_reads[] = {
rch8e6c6c42015-05-01 14:05:137351 CreateMockRead(*resp.get(), 1),
7352 CreateMockRead(*body.get(), 2),
7353 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:297354 };
7355
rch8e6c6c42015-05-01 14:05:137356 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
7357 arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067358 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]23e482282013-06-14 16:08:027359 proxy_ssl.SetNextProto(GetParam());
[email protected]511f6f52010-12-17 03:58:297360
[email protected]bb88e1d32013-05-03 23:11:077361 session_deps_.socket_factory->AddSocketDataProvider(&data);
7362 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297363
[email protected]49639fa2011-12-20 23:22:417364 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297365
mmenke6b3af6e2015-09-12 02:06:067366 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297367 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417368 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297369
[email protected]49639fa2011-12-20 23:22:417370 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297371 EXPECT_EQ(ERR_IO_PENDING, rv);
7372
7373 rv = callback.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:177374 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]511f6f52010-12-17 03:58:297375
[email protected]4eddbc732012-08-09 05:40:177376 // TODO(ttuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:297377}
7378
[email protected]0c5fb722012-02-28 11:50:357379// Test the request-challenge-retry sequence for basic auth, through
7380// a SPDY proxy over a single SPDY session.
[email protected]23e482282013-06-14 16:08:027381TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:357382 HttpRequestInfo request;
7383 request.method = "GET";
bncce36dca22015-04-21 22:11:237384 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:357385 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:297386 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]0c5fb722012-02-28 11:50:357387
7388 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037389 session_deps_.proxy_service =
7390 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
vishal.b62985ca92015-04-17 08:45:517391 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077392 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:067393 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:357394
7395 // Since we have proxy, should try to establish tunnel.
lgarrona91df87f2014-12-05 00:51:347396 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237397 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207398 scoped_ptr<SpdyFrame> rst(
7399 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]0c5fb722012-02-28 11:50:357400
7401 // After calling trans->RestartWithAuth(), this is the request we should
7402 // be issuing -- the final header line contains the credentials.
7403 const char* const kAuthCredentials[] = {
7404 "proxy-authorization", "Basic Zm9vOmJhcg==",
7405 };
[email protected]fba2dbde2013-05-24 16:09:017406 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
lgarrona91df87f2014-12-05 00:51:347407 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
bncce36dca22015-04-21 22:11:237408 HostPortPair("www.example.org", 443)));
7409 // fetch https://www.example.org/ via HTTP
7410 const char get[] =
7411 "GET / HTTP/1.1\r\n"
7412 "Host: www.example.org\r\n"
7413 "Connection: keep-alive\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:197414 scoped_ptr<SpdyFrame> wrapped_get(
[email protected]23e482282013-06-14 16:08:027415 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
[email protected]0c5fb722012-02-28 11:50:357416
7417 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137418 CreateMockWrite(*req, 0, ASYNC),
7419 CreateMockWrite(*rst, 2, ASYNC),
7420 CreateMockWrite(*connect2, 3),
7421 CreateMockWrite(*wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:357422 };
7423
7424 // The proxy responds to the connect with a 407, using a persistent
7425 // connection.
thestig9d3bb0c2015-01-24 00:49:517426 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:357427 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:357428 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
7429 };
[email protected]745aa9c2014-06-27 02:21:297430 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
7431 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:357432
[email protected]23e482282013-06-14 16:08:027433 scoped_ptr<SpdyFrame> conn_resp(
7434 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]0c5fb722012-02-28 11:50:357435 const char resp[] = "HTTP/1.1 200 OK\r\n"
7436 "Content-Length: 5\r\n\r\n";
7437
[email protected]ff98d7f02012-03-22 21:44:197438 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:027439 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
[email protected]ff98d7f02012-03-22 21:44:197440 scoped_ptr<SpdyFrame> wrapped_body(
[email protected]23e482282013-06-14 16:08:027441 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
[email protected]0c5fb722012-02-28 11:50:357442 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137443 CreateMockRead(*conn_auth_resp, 1, ASYNC),
7444 CreateMockRead(*conn_resp, 4, ASYNC),
7445 CreateMockRead(*wrapped_get_resp, 6, ASYNC),
7446 CreateMockRead(*wrapped_body, 7, ASYNC),
7447 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:357448 };
7449
rch8e6c6c42015-05-01 14:05:137450 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7451 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077452 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:357453 // Negotiate SPDY to the proxy
7454 SSLSocketDataProvider proxy(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:027455 proxy.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:077456 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:357457 // Vanilla SSL to the server
7458 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077459 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:357460
7461 TestCompletionCallback callback1;
7462
[email protected]262eec82013-03-19 21:01:367463 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507464 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0c5fb722012-02-28 11:50:357465
7466 int rv = trans->Start(&request, callback1.callback(), log.bound());
7467 EXPECT_EQ(ERR_IO_PENDING, rv);
7468
7469 rv = callback1.WaitForResult();
7470 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:467471 TestNetLogEntry::List entries;
[email protected]0c5fb722012-02-28 11:50:357472 log.GetEntries(&entries);
7473 size_t pos = ExpectLogContainsSomewhere(
7474 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7475 NetLog::PHASE_NONE);
7476 ExpectLogContainsSomewhere(
7477 entries, pos,
7478 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7479 NetLog::PHASE_NONE);
7480
7481 const HttpResponseInfo* response = trans->GetResponseInfo();
7482 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:507483 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]0c5fb722012-02-28 11:50:357484 EXPECT_EQ(407, response->headers->response_code());
7485 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7486 EXPECT_TRUE(response->auth_challenge.get() != NULL);
7487 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
7488
7489 TestCompletionCallback callback2;
7490
7491 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
7492 callback2.callback());
7493 EXPECT_EQ(ERR_IO_PENDING, rv);
7494
7495 rv = callback2.WaitForResult();
7496 EXPECT_EQ(OK, rv);
7497
7498 response = trans->GetResponseInfo();
7499 ASSERT_TRUE(response != NULL);
7500
7501 EXPECT_TRUE(response->headers->IsKeepAlive());
7502 EXPECT_EQ(200, response->headers->response_code());
7503 EXPECT_EQ(5, response->headers->GetContentLength());
7504 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7505
7506 // The password prompt info should not be set.
7507 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7508
[email protected]029c83b62013-01-24 05:28:207509 LoadTimingInfo load_timing_info;
7510 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7511 TestLoadTimingNotReusedWithPac(load_timing_info,
7512 CONNECT_TIMING_HAS_SSL_TIMES);
7513
[email protected]0c5fb722012-02-28 11:50:357514 trans.reset();
7515 session->CloseAllConnections();
7516}
7517
[email protected]7c6f7ba2012-04-03 04:09:297518// Test that an explicitly trusted SPDY proxy can push a resource from an
7519// origin that is different from that of its associated resource.
[email protected]23e482282013-06-14 16:08:027520TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
[email protected]7c6f7ba2012-04-03 04:09:297521 HttpRequestInfo request;
7522 HttpRequestInfo push_request;
7523
[email protected]7c6f7ba2012-04-03 04:09:297524 request.method = "GET";
bncce36dca22015-04-21 22:11:237525 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:297526 push_request.method = "GET";
7527 push_request.url = GURL("http://www.another-origin.com/foo.dat");
7528
[email protected]7c6f7ba2012-04-03 04:09:297529 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037530 session_deps_.proxy_service =
7531 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
vishal.b62985ca92015-04-17 08:45:517532 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077533 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:507534
7535 // Enable cross-origin push.
[email protected]bb88e1d32013-05-03 23:11:077536 session_deps_.trusted_spdy_proxy = "myproxy:70";
[email protected]61b4efc2012-04-27 18:12:507537
mmenke6b3af6e2015-09-12 02:06:067538 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:297539
[email protected]cdf8f7e72013-05-23 10:56:467540 scoped_ptr<SpdyFrame> stream1_syn(
7541 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
[email protected]7c6f7ba2012-04-03 04:09:297542
7543 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137544 CreateMockWrite(*stream1_syn, 0, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:297545 };
7546
7547 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027548 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:297549
7550 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027551 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:297552
7553 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027554 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]7c6f7ba2012-04-03 04:09:297555 0,
7556 2,
7557 1,
7558 "http://www.another-origin.com/foo.dat"));
[email protected]8a0fc822013-06-27 20:52:437559 const char kPushedData[] = "pushed";
7560 scoped_ptr<SpdyFrame> stream2_body(
7561 spdy_util_.ConstructSpdyBodyFrame(
7562 2, kPushedData, strlen(kPushedData), true));
[email protected]7c6f7ba2012-04-03 04:09:297563
7564 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137565 CreateMockRead(*stream1_reply, 1, ASYNC),
7566 CreateMockRead(*stream2_syn, 2, ASYNC),
7567 CreateMockRead(*stream1_body, 3, ASYNC),
7568 CreateMockRead(*stream2_body, 4, ASYNC),
7569 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
[email protected]7c6f7ba2012-04-03 04:09:297570 };
7571
rch8e6c6c42015-05-01 14:05:137572 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7573 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077574 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:297575 // Negotiate SPDY to the proxy
7576 SSLSocketDataProvider proxy(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:027577 proxy.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:077578 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:297579
[email protected]262eec82013-03-19 21:01:367580 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507581 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7c6f7ba2012-04-03 04:09:297582 TestCompletionCallback callback;
7583 int rv = trans->Start(&request, callback.callback(), log.bound());
7584 EXPECT_EQ(ERR_IO_PENDING, rv);
7585
7586 rv = callback.WaitForResult();
7587 EXPECT_EQ(OK, rv);
7588 const HttpResponseInfo* response = trans->GetResponseInfo();
7589
[email protected]262eec82013-03-19 21:01:367590 scoped_ptr<HttpTransaction> push_trans(
[email protected]90499482013-06-01 00:39:507591 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7592 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
[email protected]7c6f7ba2012-04-03 04:09:297593 EXPECT_EQ(ERR_IO_PENDING, rv);
7594
7595 rv = callback.WaitForResult();
7596 EXPECT_EQ(OK, rv);
7597 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
7598
7599 ASSERT_TRUE(response != NULL);
7600 EXPECT_TRUE(response->headers->IsKeepAlive());
7601
7602 EXPECT_EQ(200, response->headers->response_code());
7603 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7604
7605 std::string response_data;
7606 rv = ReadTransaction(trans.get(), &response_data);
7607 EXPECT_EQ(OK, rv);
7608 EXPECT_EQ("hello!", response_data);
7609
[email protected]029c83b62013-01-24 05:28:207610 LoadTimingInfo load_timing_info;
7611 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7612 TestLoadTimingNotReusedWithPac(load_timing_info,
7613 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7614
[email protected]7c6f7ba2012-04-03 04:09:297615 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:507616 EXPECT_TRUE(push_response->headers.get() != NULL);
[email protected]7c6f7ba2012-04-03 04:09:297617 EXPECT_EQ(200, push_response->headers->response_code());
7618
7619 rv = ReadTransaction(push_trans.get(), &response_data);
7620 EXPECT_EQ(OK, rv);
7621 EXPECT_EQ("pushed", response_data);
7622
[email protected]029c83b62013-01-24 05:28:207623 LoadTimingInfo push_load_timing_info;
7624 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
7625 TestLoadTimingReusedWithPac(push_load_timing_info);
7626 // The transactions should share a socket ID, despite being for different
7627 // origins.
7628 EXPECT_EQ(load_timing_info.socket_log_id,
7629 push_load_timing_info.socket_log_id);
7630
[email protected]7c6f7ba2012-04-03 04:09:297631 trans.reset();
7632 push_trans.reset();
7633 session->CloseAllConnections();
7634}
7635
[email protected]8c843192012-04-05 07:15:007636// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
[email protected]23e482282013-06-14 16:08:027637TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
[email protected]8c843192012-04-05 07:15:007638 HttpRequestInfo request;
7639
7640 request.method = "GET";
bncce36dca22015-04-21 22:11:237641 request.url = GURL("http://www.example.org/");
[email protected]8c843192012-04-05 07:15:007642
[email protected]8c843192012-04-05 07:15:007643 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037644 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:517645 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077646 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:507647
7648 // Enable cross-origin push.
[email protected]bb88e1d32013-05-03 23:11:077649 session_deps_.trusted_spdy_proxy = "myproxy:70";
[email protected]61b4efc2012-04-27 18:12:507650
mmenke6b3af6e2015-09-12 02:06:067651 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:007652
[email protected]cdf8f7e72013-05-23 10:56:467653 scoped_ptr<SpdyFrame> stream1_syn(
7654 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
[email protected]8c843192012-04-05 07:15:007655
7656 scoped_ptr<SpdyFrame> push_rst(
[email protected]c10b20852013-05-15 21:29:207657 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:007658
7659 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137660 CreateMockWrite(*stream1_syn, 0, ASYNC), CreateMockWrite(*push_rst, 3),
[email protected]8c843192012-04-05 07:15:007661 };
7662
7663 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027664 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8c843192012-04-05 07:15:007665
7666 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027667 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]8c843192012-04-05 07:15:007668
7669 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027670 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]8c843192012-04-05 07:15:007671 0,
7672 2,
7673 1,
7674 "https://www.another-origin.com/foo.dat"));
7675
7676 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137677 CreateMockRead(*stream1_reply, 1, ASYNC),
7678 CreateMockRead(*stream2_syn, 2, ASYNC),
7679 CreateMockRead(*stream1_body, 4, ASYNC),
7680 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
[email protected]8c843192012-04-05 07:15:007681 };
7682
rch8e6c6c42015-05-01 14:05:137683 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7684 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077685 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:007686 // Negotiate SPDY to the proxy
7687 SSLSocketDataProvider proxy(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:027688 proxy.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:077689 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:007690
[email protected]262eec82013-03-19 21:01:367691 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507692 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c843192012-04-05 07:15:007693 TestCompletionCallback callback;
7694 int rv = trans->Start(&request, callback.callback(), log.bound());
7695 EXPECT_EQ(ERR_IO_PENDING, rv);
7696
7697 rv = callback.WaitForResult();
7698 EXPECT_EQ(OK, rv);
7699 const HttpResponseInfo* response = trans->GetResponseInfo();
7700
7701 ASSERT_TRUE(response != NULL);
7702 EXPECT_TRUE(response->headers->IsKeepAlive());
7703
7704 EXPECT_EQ(200, response->headers->response_code());
7705 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7706
7707 std::string response_data;
7708 rv = ReadTransaction(trans.get(), &response_data);
7709 EXPECT_EQ(OK, rv);
7710 EXPECT_EQ("hello!", response_data);
7711
7712 trans.reset();
7713 session->CloseAllConnections();
7714}
7715
[email protected]2df19bb2010-08-25 20:13:467716// Test HTTPS connections to a site with a bad certificate, going through an
7717// HTTPS proxy
[email protected]23e482282013-06-14 16:08:027718TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037719 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]2df19bb2010-08-25 20:13:467720
7721 HttpRequestInfo request;
7722 request.method = "GET";
bncce36dca22015-04-21 22:11:237723 request.url = GURL("https://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467724 request.load_flags = 0;
7725
7726 // Attempt to fetch the URL from a server with a bad cert
7727 MockWrite bad_cert_writes[] = {
bncce36dca22015-04-21 22:11:237728 MockWrite(
7729 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7730 "Host: www.example.org\r\n"
7731 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467732 };
7733
7734 MockRead bad_cert_reads[] = {
7735 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067736 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:467737 };
7738
7739 // Attempt to fetch the URL with a good cert
7740 MockWrite good_data_writes[] = {
bncce36dca22015-04-21 22:11:237741 MockWrite(
7742 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7743 "Host: www.example.org\r\n"
7744 "Proxy-Connection: keep-alive\r\n\r\n"),
7745 MockWrite(
7746 "GET / HTTP/1.1\r\n"
7747 "Host: www.example.org\r\n"
7748 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467749 };
7750
7751 MockRead good_cert_reads[] = {
7752 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7753 MockRead("HTTP/1.0 200 OK\r\n"),
7754 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7755 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067756 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467757 };
7758
7759 StaticSocketDataProvider ssl_bad_certificate(
7760 bad_cert_reads, arraysize(bad_cert_reads),
7761 bad_cert_writes, arraysize(bad_cert_writes));
7762 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
7763 good_data_writes, arraysize(good_data_writes));
[email protected]8ddf8322012-02-23 18:08:067764 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7765 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:467766
7767 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:077768 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7769 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7770 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:467771
7772 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:077773 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7774 session_deps_.socket_factory->AddSocketDataProvider(&data);
7775 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:467776
[email protected]49639fa2011-12-20 23:22:417777 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:467778
mmenke6b3af6e2015-09-12 02:06:067779 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:467780 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417781 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2df19bb2010-08-25 20:13:467782
[email protected]49639fa2011-12-20 23:22:417783 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:467784 EXPECT_EQ(ERR_IO_PENDING, rv);
7785
7786 rv = callback.WaitForResult();
7787 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7788
[email protected]49639fa2011-12-20 23:22:417789 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]2df19bb2010-08-25 20:13:467790 EXPECT_EQ(ERR_IO_PENDING, rv);
7791
7792 rv = callback.WaitForResult();
7793 EXPECT_EQ(OK, rv);
7794
7795 const HttpResponseInfo* response = trans->GetResponseInfo();
7796
[email protected]fe2255a2011-09-20 19:37:507797 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:467798 EXPECT_EQ(100, response->headers->GetContentLength());
7799}
7800
[email protected]23e482282013-06-14 16:08:027801TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:427802 HttpRequestInfo request;
7803 request.method = "GET";
bncce36dca22015-04-21 22:11:237804 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:437805 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7806 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:427807
mmenke6b3af6e2015-09-12 02:06:067808 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277809 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417810 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277811
[email protected]1c773ea12009-04-28 19:58:427812 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237813 MockWrite(
7814 "GET / HTTP/1.1\r\n"
7815 "Host: www.example.org\r\n"
7816 "Connection: keep-alive\r\n"
7817 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:427818 };
7819
7820 // Lastly, the server responds with the actual content.
7821 MockRead data_reads[] = {
7822 MockRead("HTTP/1.0 200 OK\r\n"),
7823 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7824 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067825 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:427826 };
7827
[email protected]31a2bfe2010-02-09 08:03:397828 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7829 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:077830 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:427831
[email protected]49639fa2011-12-20 23:22:417832 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:427833
[email protected]49639fa2011-12-20 23:22:417834 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:427835 EXPECT_EQ(ERR_IO_PENDING, rv);
7836
7837 rv = callback.WaitForResult();
7838 EXPECT_EQ(OK, rv);
7839}
7840
[email protected]23e482282013-06-14 16:08:027841TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:297842 HttpRequestInfo request;
7843 request.method = "GET";
bncce36dca22015-04-21 22:11:237844 request.url = GURL("https://www.example.org/");
[email protected]da81f132010-08-18 23:39:297845 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7846 "Chromium Ultra Awesome X Edition");
7847
rdsmith82957ad2015-09-16 19:42:037848 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenke6b3af6e2015-09-12 02:06:067849 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277850 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417851 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277852
[email protected]da81f132010-08-18 23:39:297853 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237854 MockWrite(
7855 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7856 "Host: www.example.org\r\n"
7857 "Proxy-Connection: keep-alive\r\n"
7858 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]da81f132010-08-18 23:39:297859 };
7860 MockRead data_reads[] = {
7861 // Return an error, so the transaction stops here (this test isn't
7862 // interested in the rest).
7863 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7864 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7865 MockRead("Proxy-Connection: close\r\n\r\n"),
7866 };
7867
7868 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7869 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:077870 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:297871
[email protected]49639fa2011-12-20 23:22:417872 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:297873
[email protected]49639fa2011-12-20 23:22:417874 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]da81f132010-08-18 23:39:297875 EXPECT_EQ(ERR_IO_PENDING, rv);
7876
7877 rv = callback.WaitForResult();
7878 EXPECT_EQ(OK, rv);
7879}
7880
[email protected]23e482282013-06-14 16:08:027881TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:427882 HttpRequestInfo request;
7883 request.method = "GET";
bncce36dca22015-04-21 22:11:237884 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:427885 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:167886 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
7887 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:427888
mmenke6b3af6e2015-09-12 02:06:067889 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277890 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417891 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277892
[email protected]1c773ea12009-04-28 19:58:427893 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237894 MockWrite(
7895 "GET / HTTP/1.1\r\n"
7896 "Host: www.example.org\r\n"
7897 "Connection: keep-alive\r\n"
7898 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:427899 };
7900
7901 // Lastly, the server responds with the actual content.
7902 MockRead data_reads[] = {
7903 MockRead("HTTP/1.0 200 OK\r\n"),
7904 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7905 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067906 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:427907 };
7908
[email protected]31a2bfe2010-02-09 08:03:397909 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7910 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:077911 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:427912
[email protected]49639fa2011-12-20 23:22:417913 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:427914
[email protected]49639fa2011-12-20 23:22:417915 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:427916 EXPECT_EQ(ERR_IO_PENDING, rv);
7917
7918 rv = callback.WaitForResult();
7919 EXPECT_EQ(OK, rv);
7920}
7921
[email protected]23e482282013-06-14 16:08:027922TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:427923 HttpRequestInfo request;
7924 request.method = "POST";
bncce36dca22015-04-21 22:11:237925 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:427926
mmenke6b3af6e2015-09-12 02:06:067927 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277928 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417929 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277930
[email protected]1c773ea12009-04-28 19:58:427931 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237932 MockWrite(
7933 "POST / HTTP/1.1\r\n"
7934 "Host: www.example.org\r\n"
7935 "Connection: keep-alive\r\n"
7936 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:427937 };
7938
7939 // Lastly, the server responds with the actual content.
7940 MockRead data_reads[] = {
7941 MockRead("HTTP/1.0 200 OK\r\n"),
7942 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7943 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067944 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:427945 };
7946
[email protected]31a2bfe2010-02-09 08:03:397947 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7948 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:077949 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:427950
[email protected]49639fa2011-12-20 23:22:417951 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:427952
[email protected]49639fa2011-12-20 23:22:417953 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:427954 EXPECT_EQ(ERR_IO_PENDING, rv);
7955
7956 rv = callback.WaitForResult();
7957 EXPECT_EQ(OK, rv);
7958}
7959
[email protected]23e482282013-06-14 16:08:027960TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:427961 HttpRequestInfo request;
7962 request.method = "PUT";
bncce36dca22015-04-21 22:11:237963 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:427964
mmenke6b3af6e2015-09-12 02:06:067965 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277966 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417967 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277968
[email protected]1c773ea12009-04-28 19:58:427969 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237970 MockWrite(
7971 "PUT / HTTP/1.1\r\n"
7972 "Host: www.example.org\r\n"
7973 "Connection: keep-alive\r\n"
7974 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:427975 };
7976
7977 // Lastly, the server responds with the actual content.
7978 MockRead data_reads[] = {
7979 MockRead("HTTP/1.0 200 OK\r\n"),
7980 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7981 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067982 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:427983 };
7984
[email protected]31a2bfe2010-02-09 08:03:397985 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7986 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:077987 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:427988
[email protected]49639fa2011-12-20 23:22:417989 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:427990
[email protected]49639fa2011-12-20 23:22:417991 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:427992 EXPECT_EQ(ERR_IO_PENDING, rv);
7993
7994 rv = callback.WaitForResult();
7995 EXPECT_EQ(OK, rv);
7996}
7997
[email protected]23e482282013-06-14 16:08:027998TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:427999 HttpRequestInfo request;
8000 request.method = "HEAD";
bncce36dca22015-04-21 22:11:238001 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428002
mmenke6b3af6e2015-09-12 02:06:068003 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278004 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418005 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278006
[email protected]1c773ea12009-04-28 19:58:428007 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:138008 MockWrite("HEAD / HTTP/1.1\r\n"
8009 "Host: www.example.org\r\n"
8010 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428011 };
8012
8013 // Lastly, the server responds with the actual content.
8014 MockRead data_reads[] = {
8015 MockRead("HTTP/1.0 200 OK\r\n"),
8016 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8017 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068018 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428019 };
8020
[email protected]31a2bfe2010-02-09 08:03:398021 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8022 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078023 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428024
[email protected]49639fa2011-12-20 23:22:418025 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428026
[email protected]49639fa2011-12-20 23:22:418027 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428028 EXPECT_EQ(ERR_IO_PENDING, rv);
8029
8030 rv = callback.WaitForResult();
8031 EXPECT_EQ(OK, rv);
8032}
8033
[email protected]23e482282013-06-14 16:08:028034TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:428035 HttpRequestInfo request;
8036 request.method = "GET";
bncce36dca22015-04-21 22:11:238037 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428038 request.load_flags = LOAD_BYPASS_CACHE;
8039
mmenke6b3af6e2015-09-12 02:06:068040 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278041 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418042 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278043
[email protected]1c773ea12009-04-28 19:58:428044 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238045 MockWrite(
8046 "GET / HTTP/1.1\r\n"
8047 "Host: www.example.org\r\n"
8048 "Connection: keep-alive\r\n"
8049 "Pragma: no-cache\r\n"
8050 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428051 };
8052
8053 // Lastly, the server responds with the actual content.
8054 MockRead data_reads[] = {
8055 MockRead("HTTP/1.0 200 OK\r\n"),
8056 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8057 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068058 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428059 };
8060
[email protected]31a2bfe2010-02-09 08:03:398061 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8062 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078063 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428064
[email protected]49639fa2011-12-20 23:22:418065 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428066
[email protected]49639fa2011-12-20 23:22:418067 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428068 EXPECT_EQ(ERR_IO_PENDING, rv);
8069
8070 rv = callback.WaitForResult();
8071 EXPECT_EQ(OK, rv);
8072}
8073
[email protected]23e482282013-06-14 16:08:028074TEST_P(HttpNetworkTransactionTest,
[email protected]1c773ea12009-04-28 19:58:428075 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:428076 HttpRequestInfo request;
8077 request.method = "GET";
bncce36dca22015-04-21 22:11:238078 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428079 request.load_flags = LOAD_VALIDATE_CACHE;
8080
mmenke6b3af6e2015-09-12 02:06:068081 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278082 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418083 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278084
[email protected]1c773ea12009-04-28 19:58:428085 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238086 MockWrite(
8087 "GET / HTTP/1.1\r\n"
8088 "Host: www.example.org\r\n"
8089 "Connection: keep-alive\r\n"
8090 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428091 };
8092
8093 // Lastly, the server responds with the actual content.
8094 MockRead data_reads[] = {
8095 MockRead("HTTP/1.0 200 OK\r\n"),
8096 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8097 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068098 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428099 };
8100
[email protected]31a2bfe2010-02-09 08:03:398101 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8102 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078103 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428104
[email protected]49639fa2011-12-20 23:22:418105 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428106
[email protected]49639fa2011-12-20 23:22:418107 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428108 EXPECT_EQ(ERR_IO_PENDING, rv);
8109
8110 rv = callback.WaitForResult();
8111 EXPECT_EQ(OK, rv);
8112}
8113
[email protected]23e482282013-06-14 16:08:028114TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:428115 HttpRequestInfo request;
8116 request.method = "GET";
bncce36dca22015-04-21 22:11:238117 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438118 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:428119
mmenke6b3af6e2015-09-12 02:06:068120 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278121 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418122 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278123
[email protected]1c773ea12009-04-28 19:58:428124 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238125 MockWrite(
8126 "GET / HTTP/1.1\r\n"
8127 "Host: www.example.org\r\n"
8128 "Connection: keep-alive\r\n"
8129 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428130 };
8131
8132 // Lastly, the server responds with the actual content.
8133 MockRead data_reads[] = {
8134 MockRead("HTTP/1.0 200 OK\r\n"),
8135 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8136 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068137 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428138 };
8139
[email protected]31a2bfe2010-02-09 08:03:398140 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8141 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078142 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428143
[email protected]49639fa2011-12-20 23:22:418144 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428145
[email protected]49639fa2011-12-20 23:22:418146 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428147 EXPECT_EQ(ERR_IO_PENDING, rv);
8148
8149 rv = callback.WaitForResult();
8150 EXPECT_EQ(OK, rv);
8151}
8152
[email protected]23e482282013-06-14 16:08:028153TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:478154 HttpRequestInfo request;
8155 request.method = "GET";
bncce36dca22015-04-21 22:11:238156 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438157 request.extra_headers.SetHeader("referer", "www.foo.com");
8158 request.extra_headers.SetHeader("hEllo", "Kitty");
8159 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:478160
mmenke6b3af6e2015-09-12 02:06:068161 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278162 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418163 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278164
[email protected]270c6412010-03-29 22:02:478165 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238166 MockWrite(
8167 "GET / HTTP/1.1\r\n"
8168 "Host: www.example.org\r\n"
8169 "Connection: keep-alive\r\n"
8170 "referer: www.foo.com\r\n"
8171 "hEllo: Kitty\r\n"
8172 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:478173 };
8174
8175 // Lastly, the server responds with the actual content.
8176 MockRead data_reads[] = {
8177 MockRead("HTTP/1.0 200 OK\r\n"),
8178 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8179 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068180 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:478181 };
8182
8183 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8184 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078185 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:478186
[email protected]49639fa2011-12-20 23:22:418187 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:478188
[email protected]49639fa2011-12-20 23:22:418189 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]270c6412010-03-29 22:02:478190 EXPECT_EQ(ERR_IO_PENDING, rv);
8191
8192 rv = callback.WaitForResult();
8193 EXPECT_EQ(OK, rv);
8194}
8195
[email protected]23e482282013-06-14 16:08:028196TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278197 HttpRequestInfo request;
8198 request.method = "GET";
bncce36dca22015-04-21 22:11:238199 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278200 request.load_flags = 0;
8201
rdsmith82957ad2015-09-16 19:42:038202 session_deps_.proxy_service =
8203 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518204 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078205 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028206
mmenke6b3af6e2015-09-12 02:06:068207 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3cd17242009-06-23 02:59:028208 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418209 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028210
[email protected]3cd17242009-06-23 02:59:028211 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8212 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8213
8214 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238215 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8216 MockWrite(
8217 "GET / HTTP/1.1\r\n"
8218 "Host: www.example.org\r\n"
8219 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028220
8221 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:068222 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:028223 MockRead("HTTP/1.0 200 OK\r\n"),
8224 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8225 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068226 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028227 };
8228
[email protected]31a2bfe2010-02-09 08:03:398229 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8230 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078231 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028232
[email protected]49639fa2011-12-20 23:22:418233 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028234
[email protected]49639fa2011-12-20 23:22:418235 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:028236 EXPECT_EQ(ERR_IO_PENDING, rv);
8237
8238 rv = callback.WaitForResult();
8239 EXPECT_EQ(OK, rv);
8240
8241 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508242 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:028243
[email protected]029c83b62013-01-24 05:28:208244 LoadTimingInfo load_timing_info;
8245 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8246 TestLoadTimingNotReusedWithPac(load_timing_info,
8247 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8248
[email protected]3cd17242009-06-23 02:59:028249 std::string response_text;
8250 rv = ReadTransaction(trans.get(), &response_text);
8251 EXPECT_EQ(OK, rv);
8252 EXPECT_EQ("Payload", response_text);
8253}
8254
[email protected]23e482282013-06-14 16:08:028255TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278256 HttpRequestInfo request;
8257 request.method = "GET";
bncce36dca22015-04-21 22:11:238258 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278259 request.load_flags = 0;
8260
rdsmith82957ad2015-09-16 19:42:038261 session_deps_.proxy_service =
8262 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518263 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078264 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028265
mmenke6b3af6e2015-09-12 02:06:068266 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3cd17242009-06-23 02:59:028267 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418268 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028269
[email protected]3cd17242009-06-23 02:59:028270 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
8271 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8272
8273 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238274 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
8275 arraysize(write_buffer)),
8276 MockWrite(
8277 "GET / HTTP/1.1\r\n"
8278 "Host: www.example.org\r\n"
8279 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028280
8281 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018282 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
8283 arraysize(read_buffer)),
[email protected]e0c27be2009-07-15 13:09:358284 MockRead("HTTP/1.0 200 OK\r\n"),
8285 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8286 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068287 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358288 };
8289
[email protected]31a2bfe2010-02-09 08:03:398290 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8291 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078292 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358293
[email protected]8ddf8322012-02-23 18:08:068294 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078295 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:358296
[email protected]49639fa2011-12-20 23:22:418297 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358298
[email protected]49639fa2011-12-20 23:22:418299 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:358300 EXPECT_EQ(ERR_IO_PENDING, rv);
8301
8302 rv = callback.WaitForResult();
8303 EXPECT_EQ(OK, rv);
8304
[email protected]029c83b62013-01-24 05:28:208305 LoadTimingInfo load_timing_info;
8306 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8307 TestLoadTimingNotReusedWithPac(load_timing_info,
8308 CONNECT_TIMING_HAS_SSL_TIMES);
8309
[email protected]e0c27be2009-07-15 13:09:358310 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508311 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:358312
8313 std::string response_text;
8314 rv = ReadTransaction(trans.get(), &response_text);
8315 EXPECT_EQ(OK, rv);
8316 EXPECT_EQ("Payload", response_text);
8317}
8318
[email protected]23e482282013-06-14 16:08:028319TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:208320 HttpRequestInfo request;
8321 request.method = "GET";
bncce36dca22015-04-21 22:11:238322 request.url = GURL("http://www.example.org/");
[email protected]029c83b62013-01-24 05:28:208323 request.load_flags = 0;
8324
rdsmith82957ad2015-09-16 19:42:038325 session_deps_.proxy_service =
8326 ProxyService::CreateFixed("socks4://myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518327 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078328 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:208329
mmenke6b3af6e2015-09-12 02:06:068330 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:208331 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418332 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:208333
8334 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8335 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8336
8337 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238338 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8339 MockWrite(
8340 "GET / HTTP/1.1\r\n"
8341 "Host: www.example.org\r\n"
8342 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:208343
8344 MockRead data_reads[] = {
8345 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
8346 MockRead("HTTP/1.0 200 OK\r\n"),
8347 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8348 MockRead("Payload"),
8349 MockRead(SYNCHRONOUS, OK)
8350 };
8351
8352 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8353 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078354 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:208355
8356 TestCompletionCallback callback;
8357
8358 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8359 EXPECT_EQ(ERR_IO_PENDING, rv);
8360
8361 rv = callback.WaitForResult();
8362 EXPECT_EQ(OK, rv);
8363
8364 const HttpResponseInfo* response = trans->GetResponseInfo();
8365 ASSERT_TRUE(response != NULL);
8366
8367 LoadTimingInfo load_timing_info;
8368 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8369 TestLoadTimingNotReused(load_timing_info,
8370 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8371
8372 std::string response_text;
8373 rv = ReadTransaction(trans.get(), &response_text);
8374 EXPECT_EQ(OK, rv);
8375 EXPECT_EQ("Payload", response_text);
8376}
8377
[email protected]23e482282013-06-14 16:08:028378TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278379 HttpRequestInfo request;
8380 request.method = "GET";
bncce36dca22015-04-21 22:11:238381 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278382 request.load_flags = 0;
8383
rdsmith82957ad2015-09-16 19:42:038384 session_deps_.proxy_service =
8385 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518386 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078387 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358388
mmenke6b3af6e2015-09-12 02:06:068389 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e0c27be2009-07-15 13:09:358390 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418391 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358392
[email protected]e0c27be2009-07-15 13:09:358393 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8394 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378395 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238396 0x05, // Version
8397 0x01, // Command (CONNECT)
8398 0x00, // Reserved.
8399 0x03, // Address type (DOMAINNAME).
8400 0x0F, // Length of domain (15)
8401 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8402 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:378403 };
[email protected]e0c27be2009-07-15 13:09:358404 const char kSOCKS5OkResponse[] =
8405 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
8406
8407 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238408 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8409 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
8410 MockWrite(
8411 "GET / HTTP/1.1\r\n"
8412 "Host: www.example.org\r\n"
8413 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358414
8415 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018416 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8417 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]e0c27be2009-07-15 13:09:358418 MockRead("HTTP/1.0 200 OK\r\n"),
8419 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8420 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068421 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358422 };
8423
[email protected]31a2bfe2010-02-09 08:03:398424 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8425 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078426 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358427
[email protected]49639fa2011-12-20 23:22:418428 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358429
[email protected]49639fa2011-12-20 23:22:418430 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:358431 EXPECT_EQ(ERR_IO_PENDING, rv);
8432
8433 rv = callback.WaitForResult();
8434 EXPECT_EQ(OK, rv);
8435
8436 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508437 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:358438
[email protected]029c83b62013-01-24 05:28:208439 LoadTimingInfo load_timing_info;
8440 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8441 TestLoadTimingNotReusedWithPac(load_timing_info,
8442 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8443
[email protected]e0c27be2009-07-15 13:09:358444 std::string response_text;
8445 rv = ReadTransaction(trans.get(), &response_text);
8446 EXPECT_EQ(OK, rv);
8447 EXPECT_EQ("Payload", response_text);
8448}
8449
[email protected]23e482282013-06-14 16:08:028450TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278451 HttpRequestInfo request;
8452 request.method = "GET";
bncce36dca22015-04-21 22:11:238453 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278454 request.load_flags = 0;
8455
rdsmith82957ad2015-09-16 19:42:038456 session_deps_.proxy_service =
8457 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518458 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078459 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358460
mmenke6b3af6e2015-09-12 02:06:068461 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e0c27be2009-07-15 13:09:358462 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418463 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358464
[email protected]e0c27be2009-07-15 13:09:358465 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8466 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378467 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238468 0x05, // Version
8469 0x01, // Command (CONNECT)
8470 0x00, // Reserved.
8471 0x03, // Address type (DOMAINNAME).
8472 0x0F, // Length of domain (15)
8473 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8474 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:378475 };
8476
[email protected]e0c27be2009-07-15 13:09:358477 const char kSOCKS5OkResponse[] =
8478 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
8479
8480 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238481 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8482 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
8483 arraysize(kSOCKS5OkRequest)),
8484 MockWrite(
8485 "GET / HTTP/1.1\r\n"
8486 "Host: www.example.org\r\n"
8487 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358488
8489 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018490 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8491 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:028492 MockRead("HTTP/1.0 200 OK\r\n"),
8493 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8494 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068495 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028496 };
8497
[email protected]31a2bfe2010-02-09 08:03:398498 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8499 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078500 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028501
[email protected]8ddf8322012-02-23 18:08:068502 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078503 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:028504
[email protected]49639fa2011-12-20 23:22:418505 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028506
[email protected]49639fa2011-12-20 23:22:418507 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:028508 EXPECT_EQ(ERR_IO_PENDING, rv);
8509
8510 rv = callback.WaitForResult();
8511 EXPECT_EQ(OK, rv);
8512
8513 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508514 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:028515
[email protected]029c83b62013-01-24 05:28:208516 LoadTimingInfo load_timing_info;
8517 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8518 TestLoadTimingNotReusedWithPac(load_timing_info,
8519 CONNECT_TIMING_HAS_SSL_TIMES);
8520
[email protected]3cd17242009-06-23 02:59:028521 std::string response_text;
8522 rv = ReadTransaction(trans.get(), &response_text);
8523 EXPECT_EQ(OK, rv);
8524 EXPECT_EQ("Payload", response_text);
8525}
8526
[email protected]448d4ca52012-03-04 04:12:238527namespace {
8528
[email protected]04e5be32009-06-26 20:00:318529// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:068530
8531struct GroupNameTest {
8532 std::string proxy_server;
8533 std::string url;
8534 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:188535 bool ssl;
[email protected]2d731a32010-04-29 01:04:068536};
8537
mmenke6b3af6e2015-09-12 02:06:068538scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8a0fc822013-06-27 20:52:438539 NextProto next_proto,
[email protected]bb88e1d32013-05-03 23:11:078540 SpdySessionDependencies* session_deps_) {
mmenke6b3af6e2015-09-12 02:06:068541 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:068542
[email protected]30d4c022013-07-18 22:58:168543 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:538544 session->http_server_properties();
bnccacc0992015-03-20 20:22:228545 AlternativeService alternative_service(
bnc4988e432015-03-31 03:06:258546 AlternateProtocolFromNextProto(next_proto), "", 443);
bnc7dc7e1b42015-07-28 14:43:128547 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:228548 http_server_properties->SetAlternativeService(
bnc7dc7e1b42015-07-28 14:43:128549 HostPortPair("host.with.alternate", 80), alternative_service, 1.0,
8550 expiration);
[email protected]2d731a32010-04-29 01:04:068551
8552 return session;
8553}
8554
mmenke6b3af6e2015-09-12 02:06:068555int GroupNameTransactionHelper(
8556 const std::string& url,
8557 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:068558 HttpRequestInfo request;
8559 request.method = "GET";
8560 request.url = GURL(url);
8561 request.load_flags = 0;
8562
[email protected]262eec82013-03-19 21:01:368563 scoped_ptr<HttpTransaction> trans(
mmenke6b3af6e2015-09-12 02:06:068564 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278565
[email protected]49639fa2011-12-20 23:22:418566 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:068567
8568 // We do not complete this request, the dtor will clean the transaction up.
[email protected]49639fa2011-12-20 23:22:418569 return trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d731a32010-04-29 01:04:068570}
8571
[email protected]448d4ca52012-03-04 04:12:238572} // namespace
8573
[email protected]23e482282013-06-14 16:08:028574TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
[email protected]2d731a32010-04-29 01:04:068575 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238576 {
8577 "", // unused
8578 "http://www.example.org/direct",
8579 "www.example.org:80",
8580 false,
8581 },
8582 {
8583 "", // unused
8584 "http://[2001:1418:13:1::25]/direct",
8585 "[2001:1418:13:1::25]:80",
8586 false,
8587 },
[email protected]04e5be32009-06-26 20:00:318588
bncce36dca22015-04-21 22:11:238589 // SSL Tests
8590 {
8591 "", // unused
8592 "https://www.example.org/direct_ssl",
8593 "ssl/www.example.org:443",
8594 true,
8595 },
8596 {
8597 "", // unused
8598 "https://[2001:1418:13:1::25]/direct",
8599 "ssl/[2001:1418:13:1::25]:443",
8600 true,
8601 },
8602 {
8603 "", // unused
8604 "http://host.with.alternate/direct",
8605 "ssl/host.with.alternate:443",
8606 true,
8607 },
[email protected]2d731a32010-04-29 01:04:068608 };
[email protected]2ff8b312010-04-26 22:20:548609
bnc55ff9da2015-08-19 18:42:358610 session_deps_.use_alternative_services = true;
[email protected]2d731a32010-04-29 01:04:068611
viettrungluue4a8b882014-10-16 06:17:388612 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038613 session_deps_.proxy_service =
8614 ProxyService::CreateFixed(tests[i].proxy_server);
mmenke6b3af6e2015-09-12 02:06:068615 scoped_refptr<HttpNetworkSession> session(
[email protected]8a0fc822013-06-27 20:52:438616 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
[email protected]2d731a32010-04-29 01:04:068617
mmenke6b3af6e2015-09-12 02:06:068618 HttpNetworkSessionPeer peer(session);
[email protected]ab739042011-04-07 15:22:288619 CaptureGroupNameTransportSocketPool* transport_conn_pool =
8620 new CaptureGroupNameTransportSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138621 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348622 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]831e4a32013-11-14 02:14:448623 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8624 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028625 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
8626 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
dchenge3d1ddc2014-10-15 19:30:518627 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
[email protected]2d731a32010-04-29 01:04:068628
8629 EXPECT_EQ(ERR_IO_PENDING,
mmenke6b3af6e2015-09-12 02:06:068630 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:188631 if (tests[i].ssl)
8632 EXPECT_EQ(tests[i].expected_group_name,
8633 ssl_conn_pool->last_group_name_received());
8634 else
8635 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:288636 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:068637 }
[email protected]2d731a32010-04-29 01:04:068638}
8639
[email protected]23e482282013-06-14 16:08:028640TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
[email protected]2d731a32010-04-29 01:04:068641 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238642 {
8643 "http_proxy",
8644 "http://www.example.org/http_proxy_normal",
8645 "www.example.org:80",
8646 false,
8647 },
[email protected]2d731a32010-04-29 01:04:068648
bncce36dca22015-04-21 22:11:238649 // SSL Tests
8650 {
8651 "http_proxy",
8652 "https://www.example.org/http_connect_ssl",
8653 "ssl/www.example.org:443",
8654 true,
8655 },
[email protected]af3490e2010-10-16 21:02:298656
bncce36dca22015-04-21 22:11:238657 {
8658 "http_proxy",
8659 "http://host.with.alternate/direct",
8660 "ssl/host.with.alternate:443",
8661 true,
8662 },
[email protected]45499252013-01-23 17:12:568663
bncce36dca22015-04-21 22:11:238664 {
8665 "http_proxy",
8666 "ftp://ftp.google.com/http_proxy_normal",
8667 "ftp/ftp.google.com:21",
8668 false,
8669 },
[email protected]2d731a32010-04-29 01:04:068670 };
8671
bnc55ff9da2015-08-19 18:42:358672 session_deps_.use_alternative_services = true;
[email protected]2d731a32010-04-29 01:04:068673
viettrungluue4a8b882014-10-16 06:17:388674 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038675 session_deps_.proxy_service =
8676 ProxyService::CreateFixed(tests[i].proxy_server);
mmenke6b3af6e2015-09-12 02:06:068677 scoped_refptr<HttpNetworkSession> session(
[email protected]8a0fc822013-06-27 20:52:438678 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
[email protected]2d731a32010-04-29 01:04:068679
mmenke6b3af6e2015-09-12 02:06:068680 HttpNetworkSessionPeer peer(session);
[email protected]2d731a32010-04-29 01:04:068681
[email protected]e60e47a2010-07-14 03:37:188682 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:138683 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:348684 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138685 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348686 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:028687
[email protected]831e4a32013-11-14 02:14:448688 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8689 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028690 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
8691 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchenge3d1ddc2014-10-15 19:30:518692 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
[email protected]2d731a32010-04-29 01:04:068693
8694 EXPECT_EQ(ERR_IO_PENDING,
mmenke6b3af6e2015-09-12 02:06:068695 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:188696 if (tests[i].ssl)
8697 EXPECT_EQ(tests[i].expected_group_name,
8698 ssl_conn_pool->last_group_name_received());
8699 else
8700 EXPECT_EQ(tests[i].expected_group_name,
8701 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:068702 }
[email protected]2d731a32010-04-29 01:04:068703}
8704
[email protected]23e482282013-06-14 16:08:028705TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
[email protected]2d731a32010-04-29 01:04:068706 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238707 {
8708 "socks4://socks_proxy:1080",
8709 "http://www.example.org/socks4_direct",
8710 "socks4/www.example.org:80",
8711 false,
8712 },
8713 {
8714 "socks5://socks_proxy:1080",
8715 "http://www.example.org/socks5_direct",
8716 "socks5/www.example.org:80",
8717 false,
8718 },
[email protected]2d731a32010-04-29 01:04:068719
bncce36dca22015-04-21 22:11:238720 // SSL Tests
8721 {
8722 "socks4://socks_proxy:1080",
8723 "https://www.example.org/socks4_ssl",
8724 "socks4/ssl/www.example.org:443",
8725 true,
8726 },
8727 {
8728 "socks5://socks_proxy:1080",
8729 "https://www.example.org/socks5_ssl",
8730 "socks5/ssl/www.example.org:443",
8731 true,
8732 },
[email protected]af3490e2010-10-16 21:02:298733
bncce36dca22015-04-21 22:11:238734 {
8735 "socks4://socks_proxy:1080",
8736 "http://host.with.alternate/direct",
8737 "socks4/ssl/host.with.alternate:443",
8738 true,
8739 },
[email protected]04e5be32009-06-26 20:00:318740 };
8741
bnc55ff9da2015-08-19 18:42:358742 session_deps_.use_alternative_services = true;
[email protected]2ff8b312010-04-26 22:20:548743
viettrungluue4a8b882014-10-16 06:17:388744 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038745 session_deps_.proxy_service =
8746 ProxyService::CreateFixed(tests[i].proxy_server);
mmenke6b3af6e2015-09-12 02:06:068747 scoped_refptr<HttpNetworkSession> session(
[email protected]8a0fc822013-06-27 20:52:438748 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
[email protected]8b114dd72011-03-25 05:33:028749
mmenke6b3af6e2015-09-12 02:06:068750 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:318751
[email protected]e60e47a2010-07-14 03:37:188752 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:138753 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348754 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138755 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348756 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:028757
[email protected]831e4a32013-11-14 02:14:448758 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8759 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028760 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
8761 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchenge3d1ddc2014-10-15 19:30:518762 peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
[email protected]04e5be32009-06-26 20:00:318763
[email protected]262eec82013-03-19 21:01:368764 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:508765 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]04e5be32009-06-26 20:00:318766
[email protected]2d731a32010-04-29 01:04:068767 EXPECT_EQ(ERR_IO_PENDING,
mmenke6b3af6e2015-09-12 02:06:068768 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:188769 if (tests[i].ssl)
8770 EXPECT_EQ(tests[i].expected_group_name,
8771 ssl_conn_pool->last_group_name_received());
8772 else
8773 EXPECT_EQ(tests[i].expected_group_name,
8774 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:318775 }
8776}
8777
[email protected]23e482282013-06-14 16:08:028778TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:278779 HttpRequestInfo request;
8780 request.method = "GET";
bncce36dca22015-04-21 22:11:238781 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278782
rdsmith82957ad2015-09-16 19:42:038783 session_deps_.proxy_service =
8784 ProxyService::CreateFixed("myproxy:70;foobar:80");
[email protected]b59ff372009-07-15 22:04:328785
[email protected]69719062010-01-05 20:09:218786 // This simulates failure resolving all hostnames; that means we will fail
8787 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:078788 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:328789
mmenke6b3af6e2015-09-12 02:06:068790 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]9172a982009-06-06 00:30:258791 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418792 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]9172a982009-06-06 00:30:258793
[email protected]49639fa2011-12-20 23:22:418794 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:258795
[email protected]49639fa2011-12-20 23:22:418796 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9172a982009-06-06 00:30:258797 EXPECT_EQ(ERR_IO_PENDING, rv);
8798
[email protected]9172a982009-06-06 00:30:258799 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:018800 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:258801}
8802
[email protected]685af592010-05-11 19:31:248803// Base test to make sure that when the load flags for a request specify to
8804// bypass the cache, the DNS cache is not used.
[email protected]23e482282013-06-14 16:08:028805void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
[email protected]bb88e1d32013-05-03 23:11:078806 int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:278807 // Issue a request, asking to bypass the cache(s).
8808 HttpRequestInfo request;
8809 request.method = "GET";
8810 request.load_flags = load_flags;
bncce36dca22015-04-21 22:11:238811 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278812
[email protected]a2c2fb92009-07-18 07:31:048813 // Select a host resolver that does caching.
[email protected]bb88e1d32013-05-03 23:11:078814 session_deps_.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:328815
mmenke6b3af6e2015-09-12 02:06:068816 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:078817 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418818 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3b9cca42009-06-16 01:08:288819
bncce36dca22015-04-21 22:11:238820 // Warm up the host cache so it has an entry for "www.example.org".
[email protected]3b9cca42009-06-16 01:08:288821 AddressList addrlist;
[email protected]aa22b242011-11-16 18:58:298822 TestCompletionCallback callback;
[email protected]bb88e1d32013-05-03 23:11:078823 int rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:238824 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8825 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:478826 EXPECT_EQ(ERR_IO_PENDING, rv);
8827 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:288828 EXPECT_EQ(OK, rv);
8829
8830 // Verify that it was added to host cache, by doing a subsequent async lookup
8831 // and confirming it completes synchronously.
[email protected]bb88e1d32013-05-03 23:11:078832 rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:238833 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8834 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:328835 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:288836
bncce36dca22015-04-21 22:11:238837 // Inject a failure the next time that "www.example.org" is resolved. This way
[email protected]3b9cca42009-06-16 01:08:288838 // we can tell if the next lookup hit the cache, or the "network".
8839 // (cache --> success, "network" --> failure).
bncce36dca22015-04-21 22:11:238840 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
[email protected]3b9cca42009-06-16 01:08:288841
8842 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8843 // first read -- this won't be reached as the host resolution will fail first.
[email protected]8ddf8322012-02-23 18:08:068844 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:398845 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:078846 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:288847
[email protected]3b9cca42009-06-16 01:08:288848 // Run the request.
[email protected]49639fa2011-12-20 23:22:418849 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:288850 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:418851 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:288852
8853 // If we bypassed the cache, we would have gotten a failure while resolving
bncce36dca22015-04-21 22:11:238854 // "www.example.org".
[email protected]3b9cca42009-06-16 01:08:288855 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
8856}
8857
[email protected]685af592010-05-11 19:31:248858// There are multiple load flags that should trigger the host cache bypass.
8859// Test each in isolation:
[email protected]23e482282013-06-14 16:08:028860TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
[email protected]685af592010-05-11 19:31:248861 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
8862}
8863
[email protected]23e482282013-06-14 16:08:028864TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
[email protected]685af592010-05-11 19:31:248865 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
8866}
8867
[email protected]23e482282013-06-14 16:08:028868TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
[email protected]685af592010-05-11 19:31:248869 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
8870}
8871
[email protected]0877e3d2009-10-17 22:29:578872// Make sure we can handle an error when writing the request.
[email protected]23e482282013-06-14 16:08:028873TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:578874 HttpRequestInfo request;
8875 request.method = "GET";
8876 request.url = GURL("http://www.foo.com/");
8877 request.load_flags = 0;
8878
8879 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:068880 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:578881 };
[email protected]31a2bfe2010-02-09 08:03:398882 StaticSocketDataProvider data(NULL, 0,
8883 write_failure, arraysize(write_failure));
[email protected]bb88e1d32013-05-03 23:11:078884 session_deps_.socket_factory->AddSocketDataProvider(&data);
mmenke6b3af6e2015-09-12 02:06:068885 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:578886
[email protected]49639fa2011-12-20 23:22:418887 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:578888
8889 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418890 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:578891
[email protected]49639fa2011-12-20 23:22:418892 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:578893 EXPECT_EQ(ERR_IO_PENDING, rv);
8894
8895 rv = callback.WaitForResult();
8896 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
ttuttled9dbc652015-09-29 20:00:598897
8898 IPEndPoint endpoint;
8899 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
8900 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:578901}
8902
zmo9528c9f42015-08-04 22:12:088903// Check that a connection closed after the start of the headers finishes ok.
8904TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:578905 HttpRequestInfo request;
8906 request.method = "GET";
8907 request.url = GURL("http://www.foo.com/");
8908 request.load_flags = 0;
8909
8910 MockRead data_reads[] = {
8911 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:068912 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:578913 };
8914
[email protected]31a2bfe2010-02-09 08:03:398915 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:078916 session_deps_.socket_factory->AddSocketDataProvider(&data);
mmenke6b3af6e2015-09-12 02:06:068917 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:578918
[email protected]49639fa2011-12-20 23:22:418919 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:578920
8921 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418922 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:578923
[email protected]49639fa2011-12-20 23:22:418924 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:578925 EXPECT_EQ(ERR_IO_PENDING, rv);
8926
8927 rv = callback.WaitForResult();
zmo9528c9f42015-08-04 22:12:088928 EXPECT_EQ(OK, rv);
8929
8930 const HttpResponseInfo* response = trans->GetResponseInfo();
8931 ASSERT_TRUE(response != NULL);
8932
8933 EXPECT_TRUE(response->headers.get() != NULL);
8934 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8935
8936 std::string response_data;
8937 rv = ReadTransaction(trans.get(), &response_data);
8938 EXPECT_EQ(OK, rv);
8939 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:598940
8941 IPEndPoint endpoint;
8942 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
8943 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:578944}
8945
8946// Make sure that a dropped connection while draining the body for auth
8947// restart does the right thing.
[email protected]23e482282013-06-14 16:08:028948TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:578949 HttpRequestInfo request;
8950 request.method = "GET";
bncce36dca22015-04-21 22:11:238951 request.url = GURL("http://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:578952 request.load_flags = 0;
8953
8954 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238955 MockWrite(
8956 "GET / HTTP/1.1\r\n"
8957 "Host: www.example.org\r\n"
8958 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:578959 };
8960
8961 MockRead data_reads1[] = {
8962 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8963 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8964 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8965 MockRead("Content-Length: 14\r\n\r\n"),
8966 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:068967 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:578968 };
8969
[email protected]31a2bfe2010-02-09 08:03:398970 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8971 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:078972 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:578973
8974 // After calling trans->RestartWithAuth(), this is the request we should
8975 // be issuing -- the final header line contains the credentials.
8976 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238977 MockWrite(
8978 "GET / HTTP/1.1\r\n"
8979 "Host: www.example.org\r\n"
8980 "Connection: keep-alive\r\n"
8981 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:578982 };
8983
8984 // Lastly, the server responds with the actual content.
8985 MockRead data_reads2[] = {
8986 MockRead("HTTP/1.1 200 OK\r\n"),
8987 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8988 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068989 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:578990 };
8991
[email protected]31a2bfe2010-02-09 08:03:398992 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8993 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:078994 session_deps_.socket_factory->AddSocketDataProvider(&data2);
mmenke6b3af6e2015-09-12 02:06:068995 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:578996
[email protected]49639fa2011-12-20 23:22:418997 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:578998
[email protected]262eec82013-03-19 21:01:368999 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509000 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509001
[email protected]49639fa2011-12-20 23:22:419002 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579003 EXPECT_EQ(ERR_IO_PENDING, rv);
9004
9005 rv = callback1.WaitForResult();
9006 EXPECT_EQ(OK, rv);
9007
9008 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509009 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049010 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:579011
[email protected]49639fa2011-12-20 23:22:419012 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:579013
[email protected]49639fa2011-12-20 23:22:419014 rv = trans->RestartWithAuth(
9015 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]0877e3d2009-10-17 22:29:579016 EXPECT_EQ(ERR_IO_PENDING, rv);
9017
9018 rv = callback2.WaitForResult();
9019 EXPECT_EQ(OK, rv);
9020
9021 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509022 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:579023 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9024 EXPECT_EQ(100, response->headers->GetContentLength());
9025}
9026
9027// Test HTTPS connections going through a proxy that sends extra data.
[email protected]23e482282013-06-14 16:08:029028TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
rdsmith82957ad2015-09-16 19:42:039029 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]0877e3d2009-10-17 22:29:579030
9031 HttpRequestInfo request;
9032 request.method = "GET";
bncce36dca22015-04-21 22:11:239033 request.url = GURL("https://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:579034 request.load_flags = 0;
9035
9036 MockRead proxy_reads[] = {
9037 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:069038 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:579039 };
9040
[email protected]31a2bfe2010-02-09 08:03:399041 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]8ddf8322012-02-23 18:08:069042 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:579043
[email protected]bb88e1d32013-05-03 23:11:079044 session_deps_.socket_factory->AddSocketDataProvider(&data);
9045 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:579046
[email protected]49639fa2011-12-20 23:22:419047 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579048
[email protected]bb88e1d32013-05-03 23:11:079049 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:579050
mmenke6b3af6e2015-09-12 02:06:069051 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579052 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419053 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579054
[email protected]49639fa2011-12-20 23:22:419055 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579056 EXPECT_EQ(ERR_IO_PENDING, rv);
9057
9058 rv = callback.WaitForResult();
9059 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
9060}
9061
[email protected]23e482282013-06-14 16:08:029062TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:469063 HttpRequestInfo request;
9064 request.method = "GET";
bncce36dca22015-04-21 22:11:239065 request.url = GURL("http://www.example.org/");
[email protected]9492e4a2010-02-24 00:58:469066 request.load_flags = 0;
9067
mmenke6b3af6e2015-09-12 02:06:069068 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279069 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419070 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:279071
[email protected]e22e1362009-11-23 21:31:129072 MockRead data_reads[] = {
9073 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069074 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:129075 };
[email protected]9492e4a2010-02-24 00:58:469076
9077 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079078 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:469079
[email protected]49639fa2011-12-20 23:22:419080 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:469081
[email protected]49639fa2011-12-20 23:22:419082 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:469083 EXPECT_EQ(ERR_IO_PENDING, rv);
9084
9085 EXPECT_EQ(OK, callback.WaitForResult());
9086
9087 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509088 ASSERT_TRUE(response != NULL);
[email protected]9492e4a2010-02-24 00:58:469089
[email protected]90499482013-06-01 00:39:509090 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]9492e4a2010-02-24 00:58:469091 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9092
9093 std::string response_data;
9094 rv = ReadTransaction(trans.get(), &response_data);
[email protected]5543cbb2012-04-20 16:35:239095 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
[email protected]e22e1362009-11-23 21:31:129096}
9097
[email protected]23e482282013-06-14 16:08:029098TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:159099 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:529100 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
[email protected]95d88ffe2010-02-04 21:25:339101 const uint64 kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:219102 UploadFileElementReader::ScopedOverridingContentLengthForTests
9103 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:339104
[email protected]b2d26cfd2012-12-11 10:36:069105 ScopedVector<UploadElementReader> element_readers;
9106 element_readers.push_back(
skyostil4891b25b2015-06-11 11:43:459107 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
9108 temp_file_path, 0, kuint64max, base::Time()));
mmenkecbc2b712014-10-09 20:29:079109 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]329b68b2012-11-14 17:54:279110
9111 HttpRequestInfo request;
9112 request.method = "POST";
bncce36dca22015-04-21 22:11:239113 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279114 request.upload_data_stream = &upload_data_stream;
9115 request.load_flags = 0;
9116
mmenke6b3af6e2015-09-12 02:06:069117 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]329b68b2012-11-14 17:54:279118 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419119 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]95d88ffe2010-02-04 21:25:339120
9121 MockRead data_reads[] = {
9122 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9123 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069124 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:339125 };
[email protected]31a2bfe2010-02-09 08:03:399126 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079127 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:339128
[email protected]49639fa2011-12-20 23:22:419129 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:339130
[email protected]49639fa2011-12-20 23:22:419131 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:339132 EXPECT_EQ(ERR_IO_PENDING, rv);
9133
9134 rv = callback.WaitForResult();
9135 EXPECT_EQ(OK, rv);
9136
9137 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509138 ASSERT_TRUE(response != NULL);
[email protected]95d88ffe2010-02-04 21:25:339139
[email protected]90499482013-06-01 00:39:509140 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]95d88ffe2010-02-04 21:25:339141 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9142
9143 std::string response_data;
9144 rv = ReadTransaction(trans.get(), &response_data);
9145 EXPECT_EQ(OK, rv);
9146 EXPECT_EQ("hello world", response_data);
9147
[email protected]dd3aa792013-07-16 19:10:239148 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:339149}
9150
[email protected]23e482282013-06-14 16:08:029151TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:159152 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:529153 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:369154 std::string temp_file_content("Unreadable file.");
[email protected]e5c2a22e2014-03-06 20:42:309155 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
[email protected]6624b4622010-03-29 19:58:369156 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:119157 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:369158
[email protected]b2d26cfd2012-12-11 10:36:069159 ScopedVector<UploadElementReader> element_readers;
9160 element_readers.push_back(
skyostil4891b25b2015-06-11 11:43:459161 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
9162 temp_file, 0, kuint64max, base::Time()));
mmenkecbc2b712014-10-09 20:29:079163 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]329b68b2012-11-14 17:54:279164
9165 HttpRequestInfo request;
9166 request.method = "POST";
bncce36dca22015-04-21 22:11:239167 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279168 request.upload_data_stream = &upload_data_stream;
9169 request.load_flags = 0;
9170
[email protected]999dd8c2013-11-12 06:45:549171 // If we try to upload an unreadable file, the transaction should fail.
mmenke6b3af6e2015-09-12 02:06:069172 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]329b68b2012-11-14 17:54:279173 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419174 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]6624b4622010-03-29 19:58:369175
[email protected]999dd8c2013-11-12 06:45:549176 StaticSocketDataProvider data(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079177 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:369178
[email protected]49639fa2011-12-20 23:22:419179 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:369180
[email protected]49639fa2011-12-20 23:22:419181 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:369182 EXPECT_EQ(ERR_IO_PENDING, rv);
9183
9184 rv = callback.WaitForResult();
[email protected]999dd8c2013-11-12 06:45:549185 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
[email protected]6624b4622010-03-29 19:58:369186
[email protected]dd3aa792013-07-16 19:10:239187 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:369188}
9189
[email protected]02cad5d2013-10-02 08:14:039190TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
9191 class FakeUploadElementReader : public UploadElementReader {
9192 public:
9193 FakeUploadElementReader() {}
dchengb03027d2014-10-21 12:00:209194 ~FakeUploadElementReader() override {}
[email protected]02cad5d2013-10-02 08:14:039195
9196 const CompletionCallback& callback() const { return callback_; }
9197
9198 // UploadElementReader overrides:
dchengb03027d2014-10-21 12:00:209199 int Init(const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039200 callback_ = callback;
9201 return ERR_IO_PENDING;
9202 }
dchengb03027d2014-10-21 12:00:209203 uint64 GetContentLength() const override { return 0; }
9204 uint64 BytesRemaining() const override { return 0; }
9205 int Read(IOBuffer* buf,
9206 int buf_length,
9207 const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039208 return ERR_FAILED;
9209 }
9210
9211 private:
9212 CompletionCallback callback_;
9213 };
9214
9215 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
9216 ScopedVector<UploadElementReader> element_readers;
9217 element_readers.push_back(fake_reader);
mmenkecbc2b712014-10-09 20:29:079218 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]02cad5d2013-10-02 08:14:039219
9220 HttpRequestInfo request;
9221 request.method = "POST";
bncce36dca22015-04-21 22:11:239222 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:039223 request.upload_data_stream = &upload_data_stream;
9224 request.load_flags = 0;
9225
mmenke6b3af6e2015-09-12 02:06:069226 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02cad5d2013-10-02 08:14:039227 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419228 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02cad5d2013-10-02 08:14:039229
9230 StaticSocketDataProvider data;
9231 session_deps_.socket_factory->AddSocketDataProvider(&data);
9232
9233 TestCompletionCallback callback;
9234 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9235 EXPECT_EQ(ERR_IO_PENDING, rv);
9236 base::MessageLoop::current()->RunUntilIdle();
9237
9238 // Transaction is pending on request body initialization.
9239 ASSERT_FALSE(fake_reader->callback().is_null());
9240
9241 // Return Init()'s result after the transaction gets destroyed.
9242 trans.reset();
9243 fake_reader->callback().Run(OK); // Should not crash.
9244}
9245
[email protected]aeefc9e82010-02-19 16:18:279246// Tests that changes to Auth realms are treated like auth rejections.
[email protected]23e482282013-06-14 16:08:029247TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:279248 HttpRequestInfo request;
9249 request.method = "GET";
bncce36dca22015-04-21 22:11:239250 request.url = GURL("http://www.example.org/");
[email protected]aeefc9e82010-02-19 16:18:279251 request.load_flags = 0;
9252
9253 // First transaction will request a resource and receive a Basic challenge
9254 // with realm="first_realm".
9255 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239256 MockWrite(
9257 "GET / HTTP/1.1\r\n"
9258 "Host: www.example.org\r\n"
9259 "Connection: keep-alive\r\n"
9260 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279261 };
9262 MockRead data_reads1[] = {
9263 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9264 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9265 "\r\n"),
9266 };
9267
9268 // After calling trans->RestartWithAuth(), provide an Authentication header
9269 // for first_realm. The server will reject and provide a challenge with
9270 // second_realm.
9271 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239272 MockWrite(
9273 "GET / HTTP/1.1\r\n"
9274 "Host: www.example.org\r\n"
9275 "Connection: keep-alive\r\n"
9276 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
9277 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279278 };
9279 MockRead data_reads2[] = {
9280 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9281 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
9282 "\r\n"),
9283 };
9284
9285 // This again fails, and goes back to first_realm. Make sure that the
9286 // entry is removed from cache.
9287 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239288 MockWrite(
9289 "GET / HTTP/1.1\r\n"
9290 "Host: www.example.org\r\n"
9291 "Connection: keep-alive\r\n"
9292 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
9293 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279294 };
9295 MockRead data_reads3[] = {
9296 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9297 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9298 "\r\n"),
9299 };
9300
9301 // Try one last time (with the correct password) and get the resource.
9302 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:239303 MockWrite(
9304 "GET / HTTP/1.1\r\n"
9305 "Host: www.example.org\r\n"
9306 "Connection: keep-alive\r\n"
9307 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
9308 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279309 };
9310 MockRead data_reads4[] = {
9311 MockRead("HTTP/1.1 200 OK\r\n"
9312 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:509313 "Content-Length: 5\r\n"
9314 "\r\n"
9315 "hello"),
[email protected]aeefc9e82010-02-19 16:18:279316 };
9317
9318 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9319 data_writes1, arraysize(data_writes1));
9320 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9321 data_writes2, arraysize(data_writes2));
9322 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
9323 data_writes3, arraysize(data_writes3));
9324 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
9325 data_writes4, arraysize(data_writes4));
[email protected]bb88e1d32013-05-03 23:11:079326 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9327 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9328 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9329 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:279330
[email protected]49639fa2011-12-20 23:22:419331 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:279332
mmenke6b3af6e2015-09-12 02:06:069333 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0b0bf032010-09-21 18:08:509334 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419335 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509336
[email protected]aeefc9e82010-02-19 16:18:279337 // Issue the first request with Authorize headers. There should be a
9338 // password prompt for first_realm waiting to be filled in after the
9339 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419340 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:279341 EXPECT_EQ(ERR_IO_PENDING, rv);
9342 rv = callback1.WaitForResult();
9343 EXPECT_EQ(OK, rv);
9344 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509345 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049346 const AuthChallengeInfo* challenge = response->auth_challenge.get();
9347 ASSERT_FALSE(challenge == NULL);
9348 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239349 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049350 EXPECT_EQ("first_realm", challenge->realm);
9351 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279352
9353 // Issue the second request with an incorrect password. There should be a
9354 // password prompt for second_realm waiting to be filled in after the
9355 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419356 TestCompletionCallback callback2;
9357 rv = trans->RestartWithAuth(
9358 AuthCredentials(kFirst, kBaz), callback2.callback());
[email protected]aeefc9e82010-02-19 16:18:279359 EXPECT_EQ(ERR_IO_PENDING, rv);
9360 rv = callback2.WaitForResult();
9361 EXPECT_EQ(OK, rv);
9362 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509363 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049364 challenge = response->auth_challenge.get();
9365 ASSERT_FALSE(challenge == NULL);
9366 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239367 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049368 EXPECT_EQ("second_realm", challenge->realm);
9369 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279370
9371 // Issue the third request with another incorrect password. There should be
9372 // a password prompt for first_realm waiting to be filled in. If the password
9373 // prompt is not present, it indicates that the HttpAuthCacheEntry for
9374 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:419375 TestCompletionCallback callback3;
9376 rv = trans->RestartWithAuth(
9377 AuthCredentials(kSecond, kFou), callback3.callback());
[email protected]aeefc9e82010-02-19 16:18:279378 EXPECT_EQ(ERR_IO_PENDING, rv);
9379 rv = callback3.WaitForResult();
9380 EXPECT_EQ(OK, rv);
9381 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509382 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049383 challenge = response->auth_challenge.get();
9384 ASSERT_FALSE(challenge == NULL);
9385 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239386 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049387 EXPECT_EQ("first_realm", challenge->realm);
9388 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279389
9390 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:419391 TestCompletionCallback callback4;
9392 rv = trans->RestartWithAuth(
9393 AuthCredentials(kFirst, kBar), callback4.callback());
[email protected]aeefc9e82010-02-19 16:18:279394 EXPECT_EQ(ERR_IO_PENDING, rv);
9395 rv = callback4.WaitForResult();
9396 EXPECT_EQ(OK, rv);
9397 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509398 ASSERT_TRUE(response != NULL);
[email protected]aeefc9e82010-02-19 16:18:279399 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9400}
9401
bncc958faa2015-07-31 18:14:529402TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
9403 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359404 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529405
9406 std::string alternative_service_http_header =
9407 GetAlternativeServiceHttpHeader();
9408
9409 MockRead data_reads[] = {
9410 MockRead("HTTP/1.1 200 OK\r\n"),
9411 MockRead(alternative_service_http_header.c_str()),
9412 MockRead("\r\n"),
9413 MockRead("hello world"),
9414 MockRead(SYNCHRONOUS, OK),
9415 };
9416
9417 HttpRequestInfo request;
9418 request.method = "GET";
9419 request.url = GURL("http://www.example.org/");
9420 request.load_flags = 0;
9421
9422 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9423
9424 session_deps_.socket_factory->AddSocketDataProvider(&data);
9425
9426 TestCompletionCallback callback;
9427
mmenke6b3af6e2015-09-12 02:06:069428 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529429 scoped_ptr<HttpTransaction> trans(
9430 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9431
9432 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9433 EXPECT_EQ(ERR_IO_PENDING, rv);
9434
9435 HostPortPair http_host_port_pair("www.example.org", 80);
9436 HttpServerProperties& http_server_properties =
9437 *session->http_server_properties();
9438 AlternativeServiceVector alternative_service_vector =
9439 http_server_properties.GetAlternativeServices(http_host_port_pair);
9440 EXPECT_TRUE(alternative_service_vector.empty());
9441
9442 EXPECT_EQ(OK, callback.WaitForResult());
9443
9444 const HttpResponseInfo* response = trans->GetResponseInfo();
9445 ASSERT_TRUE(response != NULL);
9446 ASSERT_TRUE(response->headers.get() != NULL);
9447 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9448 EXPECT_FALSE(response->was_fetched_via_spdy);
9449 EXPECT_FALSE(response->was_npn_negotiated);
9450
9451 std::string response_data;
9452 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9453 EXPECT_EQ("hello world", response_data);
9454
9455 alternative_service_vector =
9456 http_server_properties.GetAlternativeServices(http_host_port_pair);
9457 ASSERT_EQ(1u, alternative_service_vector.size());
9458 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9459 alternative_service_vector[0].protocol);
9460 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9461 EXPECT_EQ(443, alternative_service_vector[0].port);
9462}
9463
bnc54ec34b72015-08-26 19:34:569464// Alternative Service headers must be ignored when |use_alternative_services|
9465// is false.
9466TEST_P(HttpNetworkTransactionTest, DoNotHonorAlternativeServiceHeader) {
9467 session_deps_.next_protos = SpdyNextProtos();
9468 session_deps_.use_alternative_services = false;
9469
9470 std::string alternative_service_http_header =
9471 GetAlternativeServiceHttpHeader();
9472
9473 MockRead data_reads[] = {
9474 MockRead("HTTP/1.1 200 OK\r\n"),
9475 MockRead(alternative_service_http_header.c_str()),
9476 MockRead("\r\n"),
9477 MockRead("hello world"),
9478 MockRead(SYNCHRONOUS, OK),
9479 };
9480
9481 HttpRequestInfo request;
9482 request.method = "GET";
9483 request.url = GURL("http://www.example.org/");
9484 request.load_flags = 0;
9485
9486 StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
9487
9488 session_deps_.socket_factory->AddSocketDataProvider(&data);
9489
9490 TestCompletionCallback callback;
9491
mmenke6b3af6e2015-09-12 02:06:069492 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc54ec34b72015-08-26 19:34:569493 scoped_ptr<HttpTransaction> trans(
9494 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9495
9496 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9497 EXPECT_EQ(ERR_IO_PENDING, rv);
9498
9499 HostPortPair http_host_port_pair("www.example.org", 80);
9500 HttpServerProperties& http_server_properties =
9501 *session->http_server_properties();
9502 AlternativeServiceVector alternative_service_vector =
9503 http_server_properties.GetAlternativeServices(http_host_port_pair);
9504 EXPECT_TRUE(alternative_service_vector.empty());
9505
9506 EXPECT_EQ(OK, callback.WaitForResult());
9507
9508 const HttpResponseInfo* response = trans->GetResponseInfo();
9509 ASSERT_TRUE(response != nullptr);
9510 ASSERT_TRUE(response->headers.get() != nullptr);
9511 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9512 EXPECT_FALSE(response->was_fetched_via_spdy);
9513 EXPECT_FALSE(response->was_npn_negotiated);
9514
9515 std::string response_data;
9516 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9517 EXPECT_EQ("hello world", response_data);
9518
9519 alternative_service_vector =
9520 http_server_properties.GetAlternativeServices(http_host_port_pair);
9521 EXPECT_TRUE(alternative_service_vector.empty());
9522}
9523
bncc958faa2015-07-31 18:14:529524TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) {
9525 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359526 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529527
9528 MockRead data_reads[] = {
9529 MockRead("HTTP/1.1 200 OK\r\n"),
9530 MockRead("Alt-Svc: "),
9531 MockRead(GetAlternateProtocolFromParam()),
9532 MockRead("=\"www.example.com:443\";p=1.0,"),
9533 MockRead("quic=\":1234\"\r\n\r\n"),
9534 MockRead("hello world"),
9535 MockRead(SYNCHRONOUS, OK),
9536 };
9537
9538 HttpRequestInfo request;
9539 request.method = "GET";
9540 request.url = GURL("http://www.example.org/");
9541 request.load_flags = 0;
9542
9543 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9544
9545 session_deps_.socket_factory->AddSocketDataProvider(&data);
9546
9547 TestCompletionCallback callback;
9548
mmenke6b3af6e2015-09-12 02:06:069549 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529550 scoped_ptr<HttpTransaction> trans(
9551 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9552
9553 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9554 EXPECT_EQ(ERR_IO_PENDING, rv);
9555
9556 HostPortPair http_host_port_pair("www.example.org", 80);
9557 HttpServerProperties& http_server_properties =
9558 *session->http_server_properties();
9559 AlternativeServiceVector alternative_service_vector =
9560 http_server_properties.GetAlternativeServices(http_host_port_pair);
9561 EXPECT_TRUE(alternative_service_vector.empty());
9562
9563 EXPECT_EQ(OK, callback.WaitForResult());
9564
9565 const HttpResponseInfo* response = trans->GetResponseInfo();
9566 ASSERT_TRUE(response != NULL);
9567 ASSERT_TRUE(response->headers.get() != NULL);
9568 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9569 EXPECT_FALSE(response->was_fetched_via_spdy);
9570 EXPECT_FALSE(response->was_npn_negotiated);
9571
9572 std::string response_data;
9573 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9574 EXPECT_EQ("hello world", response_data);
9575
9576 alternative_service_vector =
9577 http_server_properties.GetAlternativeServices(http_host_port_pair);
9578 ASSERT_EQ(2u, alternative_service_vector.size());
9579 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9580 alternative_service_vector[0].protocol);
9581 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9582 EXPECT_EQ(443, alternative_service_vector[0].port);
9583 EXPECT_EQ(QUIC, alternative_service_vector[1].protocol);
9584 EXPECT_EQ("www.example.org", alternative_service_vector[1].host);
9585 EXPECT_EQ(1234, alternative_service_vector[1].port);
9586}
9587
bnc54ec34b72015-08-26 19:34:569588// Alternate Protocol headers must be honored even if |use_alternative_services|
9589// is false.
[email protected]23e482282013-06-14 16:08:029590TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]d7599122014-05-24 03:37:239591 session_deps_.next_protos = SpdyNextProtos();
bnc54ec34b72015-08-26 19:34:569592 session_deps_.use_alternative_services = false;
[email protected]a2cb8122010-03-10 17:22:429593
[email protected]8a0fc822013-06-27 20:52:439594 std::string alternate_protocol_http_header =
9595 GetAlternateProtocolHttpHeader();
9596
[email protected]564b4912010-03-09 16:30:429597 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:529598 MockRead("HTTP/1.1 200 OK\r\n"),
9599 MockRead(alternate_protocol_http_header.c_str()),
9600 MockRead("\r\n"),
9601 MockRead("hello world"),
9602 MockRead(SYNCHRONOUS, OK),
[email protected]564b4912010-03-09 16:30:429603 };
9604
9605 HttpRequestInfo request;
9606 request.method = "GET";
bncce36dca22015-04-21 22:11:239607 request.url = GURL("http://www.example.org/");
[email protected]564b4912010-03-09 16:30:429608 request.load_flags = 0;
9609
9610 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9611
[email protected]bb88e1d32013-05-03 23:11:079612 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]564b4912010-03-09 16:30:429613
[email protected]49639fa2011-12-20 23:22:419614 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:429615
mmenke6b3af6e2015-09-12 02:06:069616 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:369617 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509618 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]564b4912010-03-09 16:30:429619
[email protected]49639fa2011-12-20 23:22:419620 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:429621 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:539622
bncce36dca22015-04-21 22:11:239623 HostPortPair http_host_port_pair("www.example.org", 80);
[email protected]9801e3702014-03-07 09:33:559624 HttpServerProperties& http_server_properties =
[email protected]17291a022011-10-10 07:32:539625 *session->http_server_properties();
bncd9b132e2015-07-08 05:16:109626 AlternativeServiceVector alternative_service_vector =
9627 http_server_properties.GetAlternativeServices(http_host_port_pair);
9628 EXPECT_TRUE(alternative_service_vector.empty());
[email protected]564b4912010-03-09 16:30:429629
9630 EXPECT_EQ(OK, callback.WaitForResult());
9631
9632 const HttpResponseInfo* response = trans->GetResponseInfo();
9633 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:509634 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]564b4912010-03-09 16:30:429635 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:539636 EXPECT_FALSE(response->was_fetched_via_spdy);
9637 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:429638
9639 std::string response_data;
9640 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9641 EXPECT_EQ("hello world", response_data);
9642
bncd9b132e2015-07-08 05:16:109643 alternative_service_vector =
9644 http_server_properties.GetAlternativeServices(http_host_port_pair);
9645 ASSERT_EQ(1u, alternative_service_vector.size());
9646 EXPECT_EQ(443, alternative_service_vector[0].port);
bnc181b39a2015-03-17 21:36:479647 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
bncd9b132e2015-07-08 05:16:109648 alternative_service_vector[0].protocol);
[email protected]564b4912010-03-09 16:30:429649}
9650
rch89c6e102015-03-18 18:56:529651TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
9652 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359653 session_deps_.use_alternative_services = true;
rch89c6e102015-03-18 18:56:529654
9655 MockRead data_reads[] = {
9656 MockRead("HTTP/1.1 200 OK\r\n"),
9657 MockRead("Alternate-Protocol: \r\n\r\n"),
9658 MockRead("hello world"),
9659 MockRead(SYNCHRONOUS, OK),
9660 };
9661
9662 HttpRequestInfo request;
9663 request.method = "GET";
bncce36dca22015-04-21 22:11:239664 request.url = GURL("http://www.example.org/");
rch89c6e102015-03-18 18:56:529665 request.load_flags = 0;
9666
9667 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9668
9669 session_deps_.socket_factory->AddSocketDataProvider(&data);
9670
9671 TestCompletionCallback callback;
9672
mmenke6b3af6e2015-09-12 02:06:069673 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rch89c6e102015-03-18 18:56:529674
bncce36dca22015-04-21 22:11:239675 HostPortPair http_host_port_pair("www.example.org", 80);
rch89c6e102015-03-18 18:56:529676 HttpServerProperties& http_server_properties =
9677 *session->http_server_properties();
bnccacc0992015-03-20 20:22:229678 AlternativeService alternative_service(QUIC, "", 80);
bnc7dc7e1b42015-07-28 14:43:129679 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9680 http_server_properties.SetAlternativeService(
9681 http_host_port_pair, alternative_service, 1.0, expiration);
bnccacc0992015-03-20 20:22:229682
bncd9b132e2015-07-08 05:16:109683 AlternativeServiceVector alternative_service_vector =
9684 http_server_properties.GetAlternativeServices(http_host_port_pair);
9685 ASSERT_EQ(1u, alternative_service_vector.size());
9686 EXPECT_EQ(QUIC, alternative_service_vector[0].protocol);
rch89c6e102015-03-18 18:56:529687
9688 scoped_ptr<HttpTransaction> trans(
9689 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9690
9691 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9692 EXPECT_EQ(ERR_IO_PENDING, rv);
9693
9694 EXPECT_EQ(OK, callback.WaitForResult());
9695
9696 const HttpResponseInfo* response = trans->GetResponseInfo();
9697 ASSERT_TRUE(response != NULL);
9698 ASSERT_TRUE(response->headers.get() != NULL);
9699 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9700 EXPECT_FALSE(response->was_fetched_via_spdy);
9701 EXPECT_FALSE(response->was_npn_negotiated);
9702
9703 std::string response_data;
9704 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9705 EXPECT_EQ("hello world", response_data);
9706
bncd9b132e2015-07-08 05:16:109707 alternative_service_vector =
9708 http_server_properties.GetAlternativeServices(http_host_port_pair);
9709 EXPECT_TRUE(alternative_service_vector.empty());
rch89c6e102015-03-18 18:56:529710}
9711
bncc958faa2015-07-31 18:14:529712TEST_P(HttpNetworkTransactionTest, AltSvcOverwritesAlternateProtocol) {
9713 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359714 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529715
9716 std::string alternative_service_http_header =
9717 GetAlternativeServiceHttpHeader();
9718 std::string alternate_protocol_http_header = GetAlternateProtocolHttpHeader();
9719
9720 MockRead data_reads[] = {
9721 MockRead("HTTP/1.1 200 OK\r\n"),
9722 MockRead(alternative_service_http_header.c_str()),
9723 MockRead(alternate_protocol_http_header.c_str()),
9724 MockRead("\r\n"),
9725 MockRead("hello world"),
9726 MockRead(SYNCHRONOUS, OK),
9727 };
9728
9729 HttpRequestInfo request;
9730 request.method = "GET";
9731 request.url = GURL("http://www.example.org/");
9732 request.load_flags = 0;
9733
9734 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9735
9736 session_deps_.socket_factory->AddSocketDataProvider(&data);
9737
9738 TestCompletionCallback callback;
9739
mmenke6b3af6e2015-09-12 02:06:069740 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529741 scoped_ptr<HttpTransaction> trans(
9742 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9743
9744 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9745 EXPECT_EQ(ERR_IO_PENDING, rv);
9746
9747 HostPortPair http_host_port_pair("www.example.org", 80);
9748 HttpServerProperties& http_server_properties =
9749 *session->http_server_properties();
9750 AlternativeServiceVector alternative_service_vector =
9751 http_server_properties.GetAlternativeServices(http_host_port_pair);
9752 EXPECT_TRUE(alternative_service_vector.empty());
9753
9754 EXPECT_EQ(OK, callback.WaitForResult());
9755
9756 const HttpResponseInfo* response = trans->GetResponseInfo();
9757 ASSERT_TRUE(response != NULL);
9758 ASSERT_TRUE(response->headers.get() != NULL);
9759 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9760 EXPECT_FALSE(response->was_fetched_via_spdy);
9761 EXPECT_FALSE(response->was_npn_negotiated);
9762
9763 std::string response_data;
9764 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9765 EXPECT_EQ("hello world", response_data);
9766
9767 alternative_service_vector =
9768 http_server_properties.GetAlternativeServices(http_host_port_pair);
9769 ASSERT_EQ(1u, alternative_service_vector.size());
9770 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9771 alternative_service_vector[0].protocol);
9772 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9773 EXPECT_EQ(443, alternative_service_vector[0].port);
9774}
9775
bnc54ec34b72015-08-26 19:34:569776// When |use_alternative_services| is false, do not observe alternative service
9777// entries that point to a different host.
9778TEST_P(HttpNetworkTransactionTest, DisableAlternativeServiceToDifferentHost) {
9779 session_deps_.use_alternative_services = false;
9780
9781 HttpRequestInfo request;
9782 request.method = "GET";
9783 request.url = GURL("http://www.example.org/");
9784 request.load_flags = 0;
9785
9786 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9787 StaticSocketDataProvider first_data;
9788 first_data.set_connect_data(mock_connect);
9789 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
9790
9791 MockRead data_reads[] = {
9792 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
9793 MockRead(ASYNC, OK),
9794 };
9795 StaticSocketDataProvider second_data(data_reads, arraysize(data_reads),
9796 nullptr, 0);
9797 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
9798
mmenke6b3af6e2015-09-12 02:06:069799 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc54ec34b72015-08-26 19:34:569800
9801 base::WeakPtr<HttpServerProperties> http_server_properties =
9802 session->http_server_properties();
9803 AlternativeService alternative_service(
9804 AlternateProtocolFromNextProto(GetParam()), "different.example.org", 80);
9805 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9806 http_server_properties->SetAlternativeService(
9807 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
9808
9809 scoped_ptr<HttpTransaction> trans(
9810 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9811 TestCompletionCallback callback;
9812
9813 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9814 // The connetion to origin was refused, and the alternative service should not
9815 // be used (even though mock data are there), therefore the request should
9816 // fail.
9817 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.GetResult(rv));
9818}
9819
[email protected]23e482282013-06-14 16:08:029820TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:239821 MarkBrokenAlternateProtocolAndFallback) {
bnc55ff9da2015-08-19 18:42:359822 session_deps_.use_alternative_services = true;
[email protected]564b4912010-03-09 16:30:429823
9824 HttpRequestInfo request;
9825 request.method = "GET";
bncce36dca22015-04-21 22:11:239826 request.url = GURL("http://www.example.org/");
[email protected]564b4912010-03-09 16:30:429827 request.load_flags = 0;
9828
[email protected]d973e99a2012-02-17 21:02:369829 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:429830 StaticSocketDataProvider first_data;
9831 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:079832 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]564b4912010-03-09 16:30:429833
9834 MockRead data_reads[] = {
9835 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9836 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069837 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:429838 };
9839 StaticSocketDataProvider second_data(
9840 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079841 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:429842
mmenke6b3af6e2015-09-12 02:06:069843 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:429844
[email protected]30d4c022013-07-18 22:58:169845 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:539846 session->http_server_properties();
bnc8445b3002015-03-13 01:57:099847 const HostPortPair host_port_pair = HostPortPair::FromURL(request.url);
[email protected]3912662a32011-10-04 00:51:119848 // Port must be < 1024, or the header will be ignored (since initial port was
9849 // port 80 (another restricted port).
bncd9b132e2015-07-08 05:16:109850 const AlternativeService alternative_service(
bncce36dca22015-04-21 22:11:239851 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
bncd9b132e2015-07-08 05:16:109852 666); // Port is ignored by MockConnect anyway.
bnc7dc7e1b42015-07-28 14:43:129853 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9854 http_server_properties->SetAlternativeService(
9855 host_port_pair, alternative_service, 1.0, expiration);
[email protected]564b4912010-03-09 16:30:429856
[email protected]262eec82013-03-19 21:01:369857 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509858 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:419859 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:429860
[email protected]49639fa2011-12-20 23:22:419861 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:429862 EXPECT_EQ(ERR_IO_PENDING, rv);
9863 EXPECT_EQ(OK, callback.WaitForResult());
9864
9865 const HttpResponseInfo* response = trans->GetResponseInfo();
9866 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:509867 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]564b4912010-03-09 16:30:429868 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9869
9870 std::string response_data;
9871 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9872 EXPECT_EQ("hello world", response_data);
9873
bncd9b132e2015-07-08 05:16:109874 const AlternativeServiceVector alternative_service_vector =
9875 http_server_properties->GetAlternativeServices(host_port_pair);
9876 ASSERT_EQ(1u, alternative_service_vector.size());
9877 EXPECT_EQ(alternative_service, alternative_service_vector[0]);
9878 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
9879 alternative_service_vector[0]));
[email protected]564b4912010-03-09 16:30:429880}
9881
bnc55ff9da2015-08-19 18:42:359882// Ensure that we are not allowed to redirect traffic via an alternate protocol
9883// to an unrestricted (port >= 1024) when the original traffic was on a
9884// restricted port (port < 1024). Ensure that we can redirect in all other
9885// cases.
[email protected]23e482282013-06-14 16:08:029886TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:239887 AlternateProtocolPortRestrictedBlocked) {
bnc55ff9da2015-08-19 18:42:359888 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:119889
9890 HttpRequestInfo restricted_port_request;
9891 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:239892 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:119893 restricted_port_request.load_flags = 0;
9894
[email protected]d973e99a2012-02-17 21:02:369895 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:119896 StaticSocketDataProvider first_data;
9897 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:079898 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:119899
9900 MockRead data_reads[] = {
9901 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9902 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069903 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:119904 };
9905 StaticSocketDataProvider second_data(
9906 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079907 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:119908
mmenke6b3af6e2015-09-12 02:06:069909 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:119910
[email protected]30d4c022013-07-18 22:58:169911 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:539912 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:119913 const int kUnrestrictedAlternatePort = 1024;
bnccacc0992015-03-20 20:22:229914 AlternativeService alternative_service(
bncce36dca22015-04-21 22:11:239915 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
bnccacc0992015-03-20 20:22:229916 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:129917 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:229918 http_server_properties->SetAlternativeService(
9919 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:129920 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:119921
[email protected]262eec82013-03-19 21:01:369922 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509923 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:419924 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:119925
[email protected]49639fa2011-12-20 23:22:419926 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:369927 &restricted_port_request,
9928 callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:119929 EXPECT_EQ(ERR_IO_PENDING, rv);
9930 // Invalid change to unrestricted port should fail.
9931 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
[email protected]c54c6962013-02-01 04:53:199932}
[email protected]3912662a32011-10-04 00:51:119933
bnc55ff9da2015-08-19 18:42:359934// Ensure that we are allowed to redirect traffic via an alternate protocol to
9935// an unrestricted (port >= 1024) when the original traffic was on a restricted
9936// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
[email protected]23e482282013-06-14 16:08:029937TEST_P(HttpNetworkTransactionTest,
[email protected]c54c6962013-02-01 04:53:199938 AlternateProtocolPortRestrictedPermitted) {
bnc55ff9da2015-08-19 18:42:359939 session_deps_.use_alternative_services = true;
[email protected]bb88e1d32013-05-03 23:11:079940 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:199941
9942 HttpRequestInfo restricted_port_request;
9943 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:239944 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:199945 restricted_port_request.load_flags = 0;
9946
9947 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
9948 StaticSocketDataProvider first_data;
9949 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:079950 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:199951
9952 MockRead data_reads[] = {
9953 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9954 MockRead("hello world"),
9955 MockRead(ASYNC, OK),
9956 };
9957 StaticSocketDataProvider second_data(
9958 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079959 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]c54c6962013-02-01 04:53:199960
mmenke6b3af6e2015-09-12 02:06:069961 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:199962
[email protected]30d4c022013-07-18 22:58:169963 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]c54c6962013-02-01 04:53:199964 session->http_server_properties();
9965 const int kUnrestrictedAlternatePort = 1024;
bnccacc0992015-03-20 20:22:229966 AlternativeService alternative_service(
bncce36dca22015-04-21 22:11:239967 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
bnccacc0992015-03-20 20:22:229968 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:129969 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:229970 http_server_properties->SetAlternativeService(
9971 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:129972 1.0, expiration);
[email protected]c54c6962013-02-01 04:53:199973
[email protected]262eec82013-03-19 21:01:369974 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509975 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]c54c6962013-02-01 04:53:199976 TestCompletionCallback callback;
9977
9978 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
[email protected]262eec82013-03-19 21:01:369979 &restricted_port_request,
9980 callback.callback(), BoundNetLog()));
[email protected]c54c6962013-02-01 04:53:199981 // Change to unrestricted port should succeed.
9982 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:119983}
9984
bnc55ff9da2015-08-19 18:42:359985// Ensure that we are not allowed to redirect traffic via an alternate protocol
9986// to an unrestricted (port >= 1024) when the original traffic was on a
9987// restricted port (port < 1024). Ensure that we can redirect in all other
9988// cases.
[email protected]23e482282013-06-14 16:08:029989TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:239990 AlternateProtocolPortRestrictedAllowed) {
bnc55ff9da2015-08-19 18:42:359991 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:119992
9993 HttpRequestInfo restricted_port_request;
9994 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:239995 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:119996 restricted_port_request.load_flags = 0;
9997
[email protected]d973e99a2012-02-17 21:02:369998 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:119999 StaticSocketDataProvider first_data;
10000 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710001 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110002
10003 MockRead data_reads[] = {
10004 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10005 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610006 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110007 };
10008 StaticSocketDataProvider second_data(
10009 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710010 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110011
mmenke6b3af6e2015-09-12 02:06:0610012 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110013
[email protected]30d4c022013-07-18 22:58:1610014 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310015 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110016 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210017 AlternativeService alternative_service(
bncce36dca22015-04-21 22:11:2310018 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
bnccacc0992015-03-20 20:22:2210019 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210020 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210021 http_server_properties->SetAlternativeService(
10022 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210023 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110024
[email protected]262eec82013-03-19 21:01:3610025 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010026 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110027 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110028
[email protected]49639fa2011-12-20 23:22:4110029 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:3610030 &restricted_port_request,
10031 callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110032 EXPECT_EQ(ERR_IO_PENDING, rv);
10033 // Valid change to restricted port should pass.
10034 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110035}
10036
bnc55ff9da2015-08-19 18:42:3510037// Ensure that we are not allowed to redirect traffic via an alternate protocol
10038// to an unrestricted (port >= 1024) when the original traffic was on a
10039// restricted port (port < 1024). Ensure that we can redirect in all other
10040// cases.
[email protected]23e482282013-06-14 16:08:0210041TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310042 AlternateProtocolPortUnrestrictedAllowed1) {
bnc55ff9da2015-08-19 18:42:3510043 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110044
10045 HttpRequestInfo unrestricted_port_request;
10046 unrestricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310047 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110048 unrestricted_port_request.load_flags = 0;
10049
[email protected]d973e99a2012-02-17 21:02:3610050 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110051 StaticSocketDataProvider first_data;
10052 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710053 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110054
10055 MockRead data_reads[] = {
10056 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10057 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610058 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110059 };
10060 StaticSocketDataProvider second_data(
10061 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710062 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110063
mmenke6b3af6e2015-09-12 02:06:0610064 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110065
[email protected]30d4c022013-07-18 22:58:1610066 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310067 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110068 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210069 AlternativeService alternative_service(
bncce36dca22015-04-21 22:11:2310070 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
bnccacc0992015-03-20 20:22:2210071 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210072 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210073 http_server_properties->SetAlternativeService(
10074 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210075 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110076
[email protected]262eec82013-03-19 21:01:3610077 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010078 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110079 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110080
[email protected]49639fa2011-12-20 23:22:4110081 int rv = trans->Start(
10082 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110083 EXPECT_EQ(ERR_IO_PENDING, rv);
10084 // Valid change to restricted port should pass.
10085 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110086}
10087
bnc55ff9da2015-08-19 18:42:3510088// Ensure that we are not allowed to redirect traffic via an alternate protocol
10089// to an unrestricted (port >= 1024) when the original traffic was on a
10090// restricted port (port < 1024). Ensure that we can redirect in all other
10091// cases.
[email protected]23e482282013-06-14 16:08:0210092TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310093 AlternateProtocolPortUnrestrictedAllowed2) {
bnc55ff9da2015-08-19 18:42:3510094 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110095
10096 HttpRequestInfo unrestricted_port_request;
10097 unrestricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310098 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110099 unrestricted_port_request.load_flags = 0;
10100
[email protected]d973e99a2012-02-17 21:02:3610101 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110102 StaticSocketDataProvider first_data;
10103 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710104 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110105
10106 MockRead data_reads[] = {
10107 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10108 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610109 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110110 };
10111 StaticSocketDataProvider second_data(
10112 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710113 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110114
mmenke6b3af6e2015-09-12 02:06:0610115 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110116
[email protected]30d4c022013-07-18 22:58:1610117 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310118 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2210119 const int kUnrestrictedAlternatePort = 1025;
bnccacc0992015-03-20 20:22:2210120 AlternativeService alternative_service(
bncce36dca22015-04-21 22:11:2310121 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
bnccacc0992015-03-20 20:22:2210122 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210123 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210124 http_server_properties->SetAlternativeService(
10125 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210126 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110127
[email protected]262eec82013-03-19 21:01:3610128 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010129 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110130 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110131
[email protected]49639fa2011-12-20 23:22:4110132 int rv = trans->Start(
10133 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110134 EXPECT_EQ(ERR_IO_PENDING, rv);
10135 // Valid change to an unrestricted port should pass.
10136 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110137}
10138
bnc55ff9da2015-08-19 18:42:3510139// Ensure that we are not allowed to redirect traffic via an alternate protocol
10140// to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
10141// once the alternate protocol request fails.
[email protected]d7599122014-05-24 03:37:2310142TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
bnc55ff9da2015-08-19 18:42:3510143 session_deps_.use_alternative_services = true;
[email protected]eb6234e2012-01-19 01:50:0210144
10145 HttpRequestInfo request;
10146 request.method = "GET";
bncce36dca22015-04-21 22:11:2310147 request.url = GURL("http://www.example.org/");
[email protected]eb6234e2012-01-19 01:50:0210148 request.load_flags = 0;
10149
10150 // The alternate protocol request will error out before we attempt to connect,
10151 // so only the standard HTTP request will try to connect.
10152 MockRead data_reads[] = {
10153 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10154 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610155 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0210156 };
10157 StaticSocketDataProvider data(
10158 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710159 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0210160
mmenke6b3af6e2015-09-12 02:06:0610161 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0210162
[email protected]30d4c022013-07-18 22:58:1610163 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0210164 session->http_server_properties();
10165 const int kUnsafePort = 7;
bnccacc0992015-03-20 20:22:2210166 AlternativeService alternative_service(
bncce36dca22015-04-21 22:11:2310167 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
bnccacc0992015-03-20 20:22:2210168 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1210169 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210170 http_server_properties->SetAlternativeService(
bnc7dc7e1b42015-07-28 14:43:1210171 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
[email protected]eb6234e2012-01-19 01:50:0210172
[email protected]262eec82013-03-19 21:01:3610173 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010174 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]eb6234e2012-01-19 01:50:0210175 TestCompletionCallback callback;
10176
10177 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10178 EXPECT_EQ(ERR_IO_PENDING, rv);
10179 // The HTTP request should succeed.
10180 EXPECT_EQ(OK, callback.WaitForResult());
10181
[email protected]eb6234e2012-01-19 01:50:0210182 const HttpResponseInfo* response = trans->GetResponseInfo();
10183 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010184 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]eb6234e2012-01-19 01:50:0210185 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10186
10187 std::string response_data;
10188 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10189 EXPECT_EQ("hello world", response_data);
10190}
10191
[email protected]23e482282013-06-14 16:08:0210192TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510193 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310194 session_deps_.next_protos = SpdyNextProtos();
[email protected]2ff8b312010-04-26 22:20:5410195
10196 HttpRequestInfo request;
10197 request.method = "GET";
bncce36dca22015-04-21 22:11:2310198 request.url = GURL("http://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5410199 request.load_flags = 0;
10200
[email protected]8a0fc822013-06-27 20:52:4310201 std::string alternate_protocol_http_header =
10202 GetAlternateProtocolHttpHeader();
10203
[email protected]2ff8b312010-04-26 22:20:5410204 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210205 MockRead("HTTP/1.1 200 OK\r\n"),
10206 MockRead(alternate_protocol_http_header.c_str()),
10207 MockRead("\r\n"),
10208 MockRead("hello world"),
10209 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10210 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5410211
10212 StaticSocketDataProvider first_transaction(
10213 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710214 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2ff8b312010-04-26 22:20:5410215
[email protected]8ddf8322012-02-23 18:08:0610216 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0210217 ssl.SetNextProto(GetParam());
bncce36dca22015-04-21 22:11:2310218 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10219 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710220 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2ff8b312010-04-26 22:20:5410221
[email protected]cdf8f7e72013-05-23 10:56:4610222 scoped_ptr<SpdyFrame> req(
10223 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1310224 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]2ff8b312010-04-26 22:20:5410225
[email protected]23e482282013-06-14 16:08:0210226 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10227 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5410228 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310229 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5410230 };
10231
rch8e6c6c42015-05-01 14:05:1310232 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10233 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710234 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5410235
[email protected]d973e99a2012-02-17 21:02:3610236 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510237 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10238 NULL, 0, NULL, 0);
10239 hanging_non_alternate_protocol_socket.set_connect_data(
10240 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710241 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510242 &hanging_non_alternate_protocol_socket);
10243
[email protected]49639fa2011-12-20 23:22:4110244 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5410245
mmenke6b3af6e2015-09-12 02:06:0610246 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610247 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010248 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410249
[email protected]49639fa2011-12-20 23:22:4110250 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410251 EXPECT_EQ(ERR_IO_PENDING, rv);
10252 EXPECT_EQ(OK, callback.WaitForResult());
10253
10254 const HttpResponseInfo* response = trans->GetResponseInfo();
10255 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010256 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5410257 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10258
10259 std::string response_data;
10260 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10261 EXPECT_EQ("hello world", response_data);
10262
[email protected]90499482013-06-01 00:39:5010263 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410264
[email protected]49639fa2011-12-20 23:22:4110265 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410266 EXPECT_EQ(ERR_IO_PENDING, rv);
10267 EXPECT_EQ(OK, callback.WaitForResult());
10268
10269 response = trans->GetResponseInfo();
10270 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010271 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5410272 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310273 EXPECT_TRUE(response->was_fetched_via_spdy);
10274 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5410275
10276 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10277 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5410278}
10279
[email protected]23e482282013-06-14 16:08:0210280TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
bnc55ff9da2015-08-19 18:42:3510281 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310282 session_deps_.next_protos = SpdyNextProtos();
[email protected]2d6728692011-03-12 01:39:5510283
10284 HttpRequestInfo request;
10285 request.method = "GET";
bncce36dca22015-04-21 22:11:2310286 request.url = GURL("http://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510287 request.load_flags = 0;
10288
[email protected]8a0fc822013-06-27 20:52:4310289 std::string alternate_protocol_http_header =
10290 GetAlternateProtocolHttpHeader();
10291
[email protected]2d6728692011-03-12 01:39:5510292 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210293 MockRead("HTTP/1.1 200 OK\r\n"),
10294 MockRead(alternate_protocol_http_header.c_str()),
10295 MockRead("\r\n"),
10296 MockRead("hello world"),
10297 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10298 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510299 };
10300
10301 StaticSocketDataProvider first_transaction(
10302 data_reads, arraysize(data_reads), NULL, 0);
10303 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
[email protected]bb88e1d32013-05-03 23:11:0710304 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510305
[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_socket(
10308 NULL, 0, NULL, 0);
10309 hanging_socket.set_connect_data(never_finishing_connect);
10310 // Socket 2 and 3 are the hanging Alternate-Protocol and
10311 // non-Alternate-Protocol jobs from the 2nd transaction.
[email protected]bb88e1d32013-05-03 23:11:0710312 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
10313 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
[email protected]2d6728692011-03-12 01:39:5510314
[email protected]8ddf8322012-02-23 18:08:0610315 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0210316 ssl.SetNextProto(GetParam());
bncce36dca22015-04-21 22:11:2310317 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10318 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710319 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510320
[email protected]cdf8f7e72013-05-23 10:56:4610321 scoped_ptr<SpdyFrame> req1(
10322 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10323 scoped_ptr<SpdyFrame> req2(
10324 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]2d6728692011-03-12 01:39:5510325 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1310326 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
[email protected]2d6728692011-03-12 01:39:5510327 };
[email protected]23e482282013-06-14 16:08:0210328 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10329 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
10330 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10331 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5510332 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310333 CreateMockRead(*resp1, 2),
10334 CreateMockRead(*data1, 3),
10335 CreateMockRead(*resp2, 4),
10336 CreateMockRead(*data2, 5),
10337 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5510338 };
10339
rch8e6c6c42015-05-01 14:05:1310340 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10341 arraysize(spdy_writes));
[email protected]2d6728692011-03-12 01:39:5510342 // Socket 4 is the successful Alternate-Protocol for transaction 3.
[email protected]bb88e1d32013-05-03 23:11:0710343 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5510344
10345 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
[email protected]bb88e1d32013-05-03 23:11:0710346 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
[email protected]2d6728692011-03-12 01:39:5510347
mmenke6b3af6e2015-09-12 02:06:0610348 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4110349 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5010350 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5510351
[email protected]49639fa2011-12-20 23:22:4110352 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510353 EXPECT_EQ(ERR_IO_PENDING, rv);
10354 EXPECT_EQ(OK, callback1.WaitForResult());
10355
10356 const HttpResponseInfo* response = trans1.GetResponseInfo();
10357 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010358 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510359 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10360
10361 std::string response_data;
10362 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10363 EXPECT_EQ("hello world", response_data);
10364
[email protected]49639fa2011-12-20 23:22:4110365 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5010366 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110367 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510368 EXPECT_EQ(ERR_IO_PENDING, rv);
10369
[email protected]49639fa2011-12-20 23:22:4110370 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5010371 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110372 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510373 EXPECT_EQ(ERR_IO_PENDING, rv);
10374
10375 EXPECT_EQ(OK, callback2.WaitForResult());
10376 EXPECT_EQ(OK, callback3.WaitForResult());
10377
10378 response = trans2.GetResponseInfo();
10379 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010380 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510381 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10382 EXPECT_TRUE(response->was_fetched_via_spdy);
10383 EXPECT_TRUE(response->was_npn_negotiated);
10384 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10385 EXPECT_EQ("hello!", response_data);
10386
10387 response = trans3.GetResponseInfo();
10388 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010389 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510390 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10391 EXPECT_TRUE(response->was_fetched_via_spdy);
10392 EXPECT_TRUE(response->was_npn_negotiated);
10393 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
10394 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5510395}
10396
[email protected]23e482282013-06-14 16:08:0210397TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510398 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310399 session_deps_.next_protos = SpdyNextProtos();
[email protected]2d6728692011-03-12 01:39:5510400
10401 HttpRequestInfo request;
10402 request.method = "GET";
bncce36dca22015-04-21 22:11:2310403 request.url = GURL("http://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510404 request.load_flags = 0;
10405
[email protected]8a0fc822013-06-27 20:52:4310406 std::string alternate_protocol_http_header =
10407 GetAlternateProtocolHttpHeader();
10408
[email protected]2d6728692011-03-12 01:39:5510409 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210410 MockRead("HTTP/1.1 200 OK\r\n"),
10411 MockRead(alternate_protocol_http_header.c_str()),
10412 MockRead("\r\n"),
10413 MockRead("hello world"),
10414 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10415 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510416 };
10417
10418 StaticSocketDataProvider first_transaction(
10419 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710420 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510421
[email protected]8ddf8322012-02-23 18:08:0610422 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0210423 ssl.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:0710424 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510425
[email protected]d973e99a2012-02-17 21:02:3610426 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510427 StaticSocketDataProvider hanging_alternate_protocol_socket(
10428 NULL, 0, NULL, 0);
10429 hanging_alternate_protocol_socket.set_connect_data(
10430 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710431 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510432 &hanging_alternate_protocol_socket);
10433
10434 // 2nd request is just a copy of the first one, over HTTP again.
[email protected]bb88e1d32013-05-03 23:11:0710435 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510436
[email protected]49639fa2011-12-20 23:22:4110437 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5510438
mmenke6b3af6e2015-09-12 02:06:0610439 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610440 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010441 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510442
[email protected]49639fa2011-12-20 23:22:4110443 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510444 EXPECT_EQ(ERR_IO_PENDING, rv);
10445 EXPECT_EQ(OK, callback.WaitForResult());
10446
10447 const HttpResponseInfo* response = trans->GetResponseInfo();
10448 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010449 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510450 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10451
10452 std::string response_data;
10453 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10454 EXPECT_EQ("hello world", response_data);
10455
[email protected]90499482013-06-01 00:39:5010456 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510457
[email protected]49639fa2011-12-20 23:22:4110458 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510459 EXPECT_EQ(ERR_IO_PENDING, rv);
10460 EXPECT_EQ(OK, callback.WaitForResult());
10461
10462 response = trans->GetResponseInfo();
10463 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010464 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510465 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10466 EXPECT_FALSE(response->was_fetched_via_spdy);
10467 EXPECT_FALSE(response->was_npn_negotiated);
10468
10469 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10470 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5510471}
10472
[email protected]631f1322010-04-30 17:59:1110473class CapturingProxyResolver : public ProxyResolver {
10474 public:
sammce90c9212015-05-27 23:43:3510475 CapturingProxyResolver() {}
dchengb03027d2014-10-21 12:00:2010476 ~CapturingProxyResolver() override {}
[email protected]631f1322010-04-30 17:59:1110477
dchengb03027d2014-10-21 12:00:2010478 int GetProxyForURL(const GURL& url,
10479 ProxyInfo* results,
10480 const CompletionCallback& callback,
10481 RequestHandle* request,
10482 const BoundNetLog& net_log) override {
[email protected]fae7669f2010-08-02 21:49:4010483 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
10484 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:4210485 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:1110486 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:4210487 return OK;
[email protected]631f1322010-04-30 17:59:1110488 }
10489
dchengb03027d2014-10-21 12:00:2010490 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
[email protected]631f1322010-04-30 17:59:1110491
dchengb03027d2014-10-21 12:00:2010492 LoadState GetLoadState(RequestHandle request) const override {
[email protected]f2c971f2011-11-08 00:33:1710493 NOTREACHED();
10494 return LOAD_STATE_IDLE;
10495 }
10496
[email protected]24476402010-07-20 20:55:1710497 const std::vector<GURL>& resolved() const { return resolved_; }
10498
10499 private:
[email protected]631f1322010-04-30 17:59:1110500 std::vector<GURL> resolved_;
10501
10502 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
10503};
10504
sammce64b2362015-04-29 03:50:2310505class CapturingProxyResolverFactory : public ProxyResolverFactory {
10506 public:
10507 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
10508 : ProxyResolverFactory(false), resolver_(resolver) {}
10509
10510 int CreateProxyResolver(
10511 const scoped_refptr<ProxyResolverScriptData>& pac_script,
10512 scoped_ptr<ProxyResolver>* resolver,
10513 const net::CompletionCallback& callback,
10514 scoped_ptr<Request>* request) override {
10515 resolver->reset(new ForwardingProxyResolver(resolver_));
10516 return OK;
10517 }
10518
10519 private:
10520 ProxyResolver* resolver_;
10521};
10522
[email protected]23e482282013-06-14 16:08:0210523TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310524 UseAlternateProtocolForTunneledNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510525 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310526 session_deps_.next_protos = SpdyNextProtos();
[email protected]631f1322010-04-30 17:59:1110527
10528 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4210529 proxy_config.set_auto_detect(true);
10530 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1110531
sammc5dd160c2015-04-02 02:43:1310532 CapturingProxyResolver capturing_proxy_resolver;
[email protected]bb88e1d32013-05-03 23:11:0710533 session_deps_.proxy_service.reset(new ProxyService(
csharrisonb7e3a082015-09-22 19:13:0410534 make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)),
sammc5dd160c2015-04-02 02:43:1310535 make_scoped_ptr(
sammce64b2362015-04-29 03:50:2310536 new CapturingProxyResolverFactory(&capturing_proxy_resolver)),
[email protected]66761b952010-06-25 21:30:3810537 NULL));
vishal.b62985ca92015-04-17 08:45:5110538 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710539 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1110540
10541 HttpRequestInfo request;
10542 request.method = "GET";
bncce36dca22015-04-21 22:11:2310543 request.url = GURL("http://www.example.org/");
[email protected]631f1322010-04-30 17:59:1110544 request.load_flags = 0;
10545
[email protected]8a0fc822013-06-27 20:52:4310546 std::string alternate_protocol_http_header =
10547 GetAlternateProtocolHttpHeader();
10548
[email protected]631f1322010-04-30 17:59:1110549 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210550 MockRead("HTTP/1.1 200 OK\r\n"),
10551 MockRead(alternate_protocol_http_header.c_str()),
10552 MockRead("\r\n"),
10553 MockRead("hello world"),
10554 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10555 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1110556 };
10557
10558 StaticSocketDataProvider first_transaction(
10559 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710560 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]631f1322010-04-30 17:59:1110561
[email protected]8ddf8322012-02-23 18:08:0610562 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0210563 ssl.SetNextProto(GetParam());
bncce36dca22015-04-21 22:11:2310564 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10565 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710566 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]631f1322010-04-30 17:59:1110567
[email protected]cdf8f7e72013-05-23 10:56:4610568 scoped_ptr<SpdyFrame> req(
10569 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]631f1322010-04-30 17:59:1110570 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1310571 MockWrite(ASYNC, 0,
10572 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10573 "Host: www.example.org\r\n"
10574 "Proxy-Connection: keep-alive\r\n\r\n"),
10575 CreateMockWrite(*req, 2),
[email protected]631f1322010-04-30 17:59:1110576 };
10577
[email protected]d911f1b2010-05-05 22:39:4210578 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10579
[email protected]23e482282013-06-14 16:08:0210580 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10581 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:1110582 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310583 MockRead(ASYNC, 1, kCONNECTResponse),
10584 CreateMockRead(*resp.get(), 3),
10585 CreateMockRead(*data.get(), 4),
10586 MockRead(ASYNC, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1110587 };
10588
rch8e6c6c42015-05-01 14:05:1310589 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10590 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710591 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1110592
[email protected]d973e99a2012-02-17 21:02:3610593 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510594 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10595 NULL, 0, NULL, 0);
10596 hanging_non_alternate_protocol_socket.set_connect_data(
10597 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710598 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510599 &hanging_non_alternate_protocol_socket);
10600
[email protected]49639fa2011-12-20 23:22:4110601 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1110602
mmenke6b3af6e2015-09-12 02:06:0610603 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610604 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010605 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1110606
[email protected]49639fa2011-12-20 23:22:4110607 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:1110608 EXPECT_EQ(ERR_IO_PENDING, rv);
10609 EXPECT_EQ(OK, callback.WaitForResult());
10610
10611 const HttpResponseInfo* response = trans->GetResponseInfo();
10612 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010613 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]631f1322010-04-30 17:59:1110614 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310615 EXPECT_FALSE(response->was_fetched_via_spdy);
10616 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:1110617
10618 std::string response_data;
10619 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10620 EXPECT_EQ("hello world", response_data);
10621
[email protected]90499482013-06-01 00:39:5010622 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1110623
[email protected]49639fa2011-12-20 23:22:4110624 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:1110625 EXPECT_EQ(ERR_IO_PENDING, rv);
10626 EXPECT_EQ(OK, callback.WaitForResult());
10627
10628 response = trans->GetResponseInfo();
10629 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010630 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]631f1322010-04-30 17:59:1110631 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310632 EXPECT_TRUE(response->was_fetched_via_spdy);
10633 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:1110634
10635 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10636 EXPECT_EQ("hello!", response_data);
sammc5dd160c2015-04-02 02:43:1310637 ASSERT_EQ(3u, capturing_proxy_resolver.resolved().size());
bncce36dca22015-04-21 22:11:2310638 EXPECT_EQ("http://www.example.org/",
sammc5dd160c2015-04-02 02:43:1310639 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2310640 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1310641 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1110642
[email protected]029c83b62013-01-24 05:28:2010643 LoadTimingInfo load_timing_info;
10644 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10645 TestLoadTimingNotReusedWithPac(load_timing_info,
10646 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1110647}
[email protected]631f1322010-04-30 17:59:1110648
[email protected]23e482282013-06-14 16:08:0210649TEST_P(HttpNetworkTransactionTest,
[email protected]2ff8b312010-04-26 22:20:5410650 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
bnc55ff9da2015-08-19 18:42:3510651 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310652 session_deps_.next_protos = SpdyNextProtos();
[email protected]2ff8b312010-04-26 22:20:5410653
10654 HttpRequestInfo request;
10655 request.method = "GET";
bncce36dca22015-04-21 22:11:2310656 request.url = GURL("http://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5410657 request.load_flags = 0;
10658
[email protected]8a0fc822013-06-27 20:52:4310659 std::string alternate_protocol_http_header =
10660 GetAlternateProtocolHttpHeader();
10661
[email protected]2ff8b312010-04-26 22:20:5410662 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210663 MockRead("HTTP/1.1 200 OK\r\n"),
10664 MockRead(alternate_protocol_http_header.c_str()),
10665 MockRead("\r\n"),
10666 MockRead("hello world"),
10667 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5410668 };
10669
10670 StaticSocketDataProvider first_transaction(
10671 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710672 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2ff8b312010-04-26 22:20:5410673
[email protected]8ddf8322012-02-23 18:08:0610674 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0210675 ssl.SetNextProto(GetParam());
bncce36dca22015-04-21 22:11:2310676 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10677 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710678 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2ff8b312010-04-26 22:20:5410679
[email protected]cdf8f7e72013-05-23 10:56:4610680 scoped_ptr<SpdyFrame> req(
10681 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1310682 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]2ff8b312010-04-26 22:20:5410683
[email protected]23e482282013-06-14 16:08:0210684 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10685 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5410686 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310687 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5410688 };
10689
rch8e6c6c42015-05-01 14:05:1310690 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10691 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710692 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5410693
[email protected]83039bb2011-12-09 18:43:5510694 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5410695
mmenke6b3af6e2015-09-12 02:06:0610696 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5410697
[email protected]262eec82013-03-19 21:01:3610698 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010699 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410700
[email protected]49639fa2011-12-20 23:22:4110701 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410702 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4110703 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:5410704
10705 const HttpResponseInfo* response = trans->GetResponseInfo();
10706 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010707 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5410708 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10709
10710 std::string response_data;
10711 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10712 EXPECT_EQ("hello world", response_data);
10713
10714 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2310715 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4010716 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5310717 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2710718 base::WeakPtr<SpdySession> spdy_session =
mmenke6b3af6e2015-09-12 02:06:0610719 CreateSecureSpdySession(session, key, BoundNetLog());
[email protected]02b0c342010-09-25 21:09:3810720
[email protected]90499482013-06-01 00:39:5010721 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410722
[email protected]49639fa2011-12-20 23:22:4110723 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410724 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4110725 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:5410726
10727 response = trans->GetResponseInfo();
10728 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010729 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5410730 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310731 EXPECT_TRUE(response->was_fetched_via_spdy);
10732 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5410733
10734 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10735 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4210736}
10737
[email protected]044de0642010-06-17 10:42:1510738// GenerateAuthToken is a mighty big test.
10739// It tests all permutation of GenerateAuthToken behavior:
10740// - Synchronous and Asynchronous completion.
10741// - OK or error on completion.
10742// - Direct connection, non-authenticating proxy, and authenticating proxy.
10743// - HTTP or HTTPS backend (to include proxy tunneling).
10744// - Non-authenticating and authenticating backend.
10745//
[email protected]fe3b7dc2012-02-03 19:52:0910746// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1510747// problems generating an auth token for an authenticating proxy, we don't
10748// need to test all permutations of the backend server).
10749//
10750// The test proceeds by going over each of the configuration cases, and
10751// potentially running up to three rounds in each of the tests. The TestConfig
10752// specifies both the configuration for the test as well as the expectations
10753// for the results.
[email protected]23e482282013-06-14 16:08:0210754TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5010755 static const char kServer[] = "http://www.example.com";
10756 static const char kSecureServer[] = "https://www.example.com";
10757 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1510758 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
10759
10760 enum AuthTiming {
10761 AUTH_NONE,
10762 AUTH_SYNC,
10763 AUTH_ASYNC,
10764 };
10765
10766 const MockWrite kGet(
10767 "GET / HTTP/1.1\r\n"
10768 "Host: www.example.com\r\n"
10769 "Connection: keep-alive\r\n\r\n");
10770 const MockWrite kGetProxy(
10771 "GET http://www.example.com/ HTTP/1.1\r\n"
10772 "Host: www.example.com\r\n"
10773 "Proxy-Connection: keep-alive\r\n\r\n");
10774 const MockWrite kGetAuth(
10775 "GET / HTTP/1.1\r\n"
10776 "Host: www.example.com\r\n"
10777 "Connection: keep-alive\r\n"
10778 "Authorization: auth_token\r\n\r\n");
10779 const MockWrite kGetProxyAuth(
10780 "GET http://www.example.com/ HTTP/1.1\r\n"
10781 "Host: www.example.com\r\n"
10782 "Proxy-Connection: keep-alive\r\n"
10783 "Proxy-Authorization: auth_token\r\n\r\n");
10784 const MockWrite kGetAuthThroughProxy(
10785 "GET http://www.example.com/ HTTP/1.1\r\n"
10786 "Host: www.example.com\r\n"
10787 "Proxy-Connection: keep-alive\r\n"
10788 "Authorization: auth_token\r\n\r\n");
10789 const MockWrite kGetAuthWithProxyAuth(
10790 "GET http://www.example.com/ HTTP/1.1\r\n"
10791 "Host: www.example.com\r\n"
10792 "Proxy-Connection: keep-alive\r\n"
10793 "Proxy-Authorization: auth_token\r\n"
10794 "Authorization: auth_token\r\n\r\n");
10795 const MockWrite kConnect(
10796 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10797 "Host: www.example.com\r\n"
10798 "Proxy-Connection: keep-alive\r\n\r\n");
10799 const MockWrite kConnectProxyAuth(
10800 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10801 "Host: www.example.com\r\n"
10802 "Proxy-Connection: keep-alive\r\n"
10803 "Proxy-Authorization: auth_token\r\n\r\n");
10804
10805 const MockRead kSuccess(
10806 "HTTP/1.1 200 OK\r\n"
10807 "Content-Type: text/html; charset=iso-8859-1\r\n"
10808 "Content-Length: 3\r\n\r\n"
10809 "Yes");
10810 const MockRead kFailure(
10811 "Should not be called.");
10812 const MockRead kServerChallenge(
10813 "HTTP/1.1 401 Unauthorized\r\n"
10814 "WWW-Authenticate: Mock realm=server\r\n"
10815 "Content-Type: text/html; charset=iso-8859-1\r\n"
10816 "Content-Length: 14\r\n\r\n"
10817 "Unauthorized\r\n");
10818 const MockRead kProxyChallenge(
10819 "HTTP/1.1 407 Unauthorized\r\n"
10820 "Proxy-Authenticate: Mock realm=proxy\r\n"
10821 "Proxy-Connection: close\r\n"
10822 "Content-Type: text/html; charset=iso-8859-1\r\n"
10823 "Content-Length: 14\r\n\r\n"
10824 "Unauthorized\r\n");
10825 const MockRead kProxyConnected(
10826 "HTTP/1.1 200 Connection Established\r\n\r\n");
10827
10828 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
10829 // no constructors, but the C++ compiler on Windows warns about
10830 // unspecified data in compound literals. So, moved to using constructors,
10831 // and TestRound's created with the default constructor should not be used.
10832 struct TestRound {
10833 TestRound()
10834 : expected_rv(ERR_UNEXPECTED),
10835 extra_write(NULL),
10836 extra_read(NULL) {
10837 }
10838 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
10839 int expected_rv_arg)
10840 : write(write_arg),
10841 read(read_arg),
10842 expected_rv(expected_rv_arg),
10843 extra_write(NULL),
10844 extra_read(NULL) {
10845 }
10846 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
10847 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0110848 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1510849 : write(write_arg),
10850 read(read_arg),
10851 expected_rv(expected_rv_arg),
10852 extra_write(extra_write_arg),
10853 extra_read(extra_read_arg) {
10854 }
10855 MockWrite write;
10856 MockRead read;
10857 int expected_rv;
10858 const MockWrite* extra_write;
10859 const MockRead* extra_read;
10860 };
10861
10862 static const int kNoSSL = 500;
10863
10864 struct TestConfig {
thestig9d3bb0c2015-01-24 00:49:5110865 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1510866 AuthTiming proxy_auth_timing;
10867 int proxy_auth_rv;
thestig9d3bb0c2015-01-24 00:49:5110868 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1510869 AuthTiming server_auth_timing;
10870 int server_auth_rv;
10871 int num_auth_rounds;
10872 int first_ssl_round;
10873 TestRound rounds[3];
10874 } test_configs[] = {
10875 // Non-authenticating HTTP server with a direct connection.
10876 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
10877 { TestRound(kGet, kSuccess, OK)}},
10878 // Authenticating HTTP server with a direct connection.
10879 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
10880 { TestRound(kGet, kServerChallenge, OK),
10881 TestRound(kGetAuth, kSuccess, OK)}},
10882 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
10883 { TestRound(kGet, kServerChallenge, OK),
10884 TestRound(kGetAuth, kFailure, kAuthErr)}},
10885 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
10886 { TestRound(kGet, kServerChallenge, OK),
10887 TestRound(kGetAuth, kSuccess, OK)}},
10888 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
10889 { TestRound(kGet, kServerChallenge, OK),
10890 TestRound(kGetAuth, kFailure, kAuthErr)}},
10891 // Non-authenticating HTTP server through a non-authenticating proxy.
10892 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
10893 { TestRound(kGetProxy, kSuccess, OK)}},
10894 // Authenticating HTTP server through a non-authenticating proxy.
10895 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
10896 { TestRound(kGetProxy, kServerChallenge, OK),
10897 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
10898 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
10899 { TestRound(kGetProxy, kServerChallenge, OK),
10900 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
10901 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
10902 { TestRound(kGetProxy, kServerChallenge, OK),
10903 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
10904 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
10905 { TestRound(kGetProxy, kServerChallenge, OK),
10906 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
10907 // Non-authenticating HTTP server through an authenticating proxy.
10908 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
10909 { TestRound(kGetProxy, kProxyChallenge, OK),
10910 TestRound(kGetProxyAuth, kSuccess, OK)}},
10911 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
10912 { TestRound(kGetProxy, kProxyChallenge, OK),
10913 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
10914 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
10915 { TestRound(kGetProxy, kProxyChallenge, OK),
10916 TestRound(kGetProxyAuth, kSuccess, OK)}},
10917 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
10918 { TestRound(kGetProxy, kProxyChallenge, OK),
10919 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
10920 // Authenticating HTTP server through an authenticating proxy.
10921 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
10922 { TestRound(kGetProxy, kProxyChallenge, OK),
10923 TestRound(kGetProxyAuth, kServerChallenge, OK),
10924 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10925 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
10926 { TestRound(kGetProxy, kProxyChallenge, OK),
10927 TestRound(kGetProxyAuth, kServerChallenge, OK),
10928 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10929 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
10930 { TestRound(kGetProxy, kProxyChallenge, OK),
10931 TestRound(kGetProxyAuth, kServerChallenge, OK),
10932 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10933 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
10934 { TestRound(kGetProxy, kProxyChallenge, OK),
10935 TestRound(kGetProxyAuth, kServerChallenge, OK),
10936 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10937 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
10938 { TestRound(kGetProxy, kProxyChallenge, OK),
10939 TestRound(kGetProxyAuth, kServerChallenge, OK),
10940 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10941 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
10942 { TestRound(kGetProxy, kProxyChallenge, OK),
10943 TestRound(kGetProxyAuth, kServerChallenge, OK),
10944 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10945 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
10946 { TestRound(kGetProxy, kProxyChallenge, OK),
10947 TestRound(kGetProxyAuth, kServerChallenge, OK),
10948 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
10949 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
10950 { TestRound(kGetProxy, kProxyChallenge, OK),
10951 TestRound(kGetProxyAuth, kServerChallenge, OK),
10952 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
10953 // Non-authenticating HTTPS server with a direct connection.
10954 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
10955 { TestRound(kGet, kSuccess, OK)}},
10956 // Authenticating HTTPS server with a direct connection.
10957 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10958 { TestRound(kGet, kServerChallenge, OK),
10959 TestRound(kGetAuth, kSuccess, OK)}},
10960 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10961 { TestRound(kGet, kServerChallenge, OK),
10962 TestRound(kGetAuth, kFailure, kAuthErr)}},
10963 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10964 { TestRound(kGet, kServerChallenge, OK),
10965 TestRound(kGetAuth, kSuccess, OK)}},
10966 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10967 { TestRound(kGet, kServerChallenge, OK),
10968 TestRound(kGetAuth, kFailure, kAuthErr)}},
10969 // Non-authenticating HTTPS server with a non-authenticating proxy.
10970 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
10971 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
10972 // Authenticating HTTPS server through a non-authenticating proxy.
10973 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
10974 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10975 TestRound(kGetAuth, kSuccess, OK)}},
10976 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
10977 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10978 TestRound(kGetAuth, kFailure, kAuthErr)}},
10979 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
10980 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10981 TestRound(kGetAuth, kSuccess, OK)}},
10982 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
10983 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
10984 TestRound(kGetAuth, kFailure, kAuthErr)}},
10985 // Non-Authenticating HTTPS server through an authenticating proxy.
10986 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10987 { TestRound(kConnect, kProxyChallenge, OK),
10988 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10989 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10990 { TestRound(kConnect, kProxyChallenge, OK),
10991 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10992 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
10993 { TestRound(kConnect, kProxyChallenge, OK),
10994 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
10995 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
10996 { TestRound(kConnect, kProxyChallenge, OK),
10997 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
10998 // Authenticating HTTPS server through an authenticating proxy.
10999 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11000 { TestRound(kConnect, kProxyChallenge, OK),
11001 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11002 &kGet, &kServerChallenge),
11003 TestRound(kGetAuth, kSuccess, OK)}},
11004 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11005 { TestRound(kConnect, kProxyChallenge, OK),
11006 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11007 &kGet, &kServerChallenge),
11008 TestRound(kGetAuth, kFailure, kAuthErr)}},
11009 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11010 { TestRound(kConnect, kProxyChallenge, OK),
11011 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11012 &kGet, &kServerChallenge),
11013 TestRound(kGetAuth, kSuccess, OK)}},
11014 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11015 { TestRound(kConnect, kProxyChallenge, OK),
11016 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11017 &kGet, &kServerChallenge),
11018 TestRound(kGetAuth, kFailure, kAuthErr)}},
11019 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11020 { TestRound(kConnect, kProxyChallenge, OK),
11021 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11022 &kGet, &kServerChallenge),
11023 TestRound(kGetAuth, kSuccess, OK)}},
11024 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11025 { TestRound(kConnect, kProxyChallenge, OK),
11026 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11027 &kGet, &kServerChallenge),
11028 TestRound(kGetAuth, kFailure, kAuthErr)}},
11029 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11030 { TestRound(kConnect, kProxyChallenge, OK),
11031 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11032 &kGet, &kServerChallenge),
11033 TestRound(kGetAuth, kSuccess, OK)}},
11034 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11035 { TestRound(kConnect, kProxyChallenge, OK),
11036 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11037 &kGet, &kServerChallenge),
11038 TestRound(kGetAuth, kFailure, kAuthErr)}},
11039 };
11040
viettrungluue4a8b882014-10-16 06:17:3811041 for (size_t i = 0; i < arraysize(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:0811042 HttpAuthHandlerMock::Factory* auth_factory(
11043 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711044 session_deps_.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:1511045 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:2611046
11047 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1511048 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:0811049 for (int n = 0; n < 2; n++) {
11050 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11051 std::string auth_challenge = "Mock realm=proxy";
11052 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2411053 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11054 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0811055 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
11056 origin, BoundNetLog());
11057 auth_handler->SetGenerateExpectation(
11058 test_config.proxy_auth_timing == AUTH_ASYNC,
11059 test_config.proxy_auth_rv);
11060 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
11061 }
[email protected]044de0642010-06-17 10:42:1511062 }
11063 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0011064 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1511065 std::string auth_challenge = "Mock realm=server";
11066 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2411067 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11068 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1511069 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
11070 origin, BoundNetLog());
11071 auth_handler->SetGenerateExpectation(
11072 test_config.server_auth_timing == AUTH_ASYNC,
11073 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:0811074 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1511075 }
11076 if (test_config.proxy_url) {
rdsmith82957ad2015-09-16 19:42:0311077 session_deps_.proxy_service =
11078 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:1511079 } else {
rdsmith82957ad2015-09-16 19:42:0311080 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1511081 }
11082
11083 HttpRequestInfo request;
11084 request.method = "GET";
11085 request.url = GURL(test_config.server_url);
11086 request.load_flags = 0;
11087
mmenke6b3af6e2015-09-12 02:06:0611088 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
dcheng48459ac22014-08-26 00:46:4111089 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]044de0642010-06-17 10:42:1511090
rchcb68dc62015-05-21 04:45:3611091 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
11092
11093 std::vector<std::vector<MockRead>> mock_reads(1);
11094 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1511095 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11096 const TestRound& read_write_round = test_config.rounds[round];
11097
11098 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3611099 mock_reads.back().push_back(read_write_round.read);
11100 mock_writes.back().push_back(read_write_round.write);
11101
11102 // kProxyChallenge uses Proxy-Connection: close which means that the
11103 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5411104 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3611105 mock_reads.push_back(std::vector<MockRead>());
11106 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1511107 }
11108
rchcb68dc62015-05-21 04:45:3611109 if (read_write_round.extra_read) {
11110 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1511111 }
rchcb68dc62015-05-21 04:45:3611112 if (read_write_round.extra_write) {
11113 mock_writes.back().push_back(*read_write_round.extra_write);
11114 }
[email protected]044de0642010-06-17 10:42:1511115
11116 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1511117 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0711118 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1511119 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3611120 }
[email protected]044de0642010-06-17 10:42:1511121
rchcb68dc62015-05-21 04:45:3611122 ScopedVector<StaticSocketDataProvider> data_providers;
11123 for (size_t i = 0; i < mock_reads.size(); ++i) {
11124 data_providers.push_back(new StaticSocketDataProvider(
11125 vector_as_array(&mock_reads[i]), mock_reads[i].size(),
11126 vector_as_array(&mock_writes[i]), mock_writes[i].size()));
11127 session_deps_.socket_factory->AddSocketDataProvider(
11128 data_providers.back());
11129 }
11130
11131 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11132 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1511133 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4111134 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1511135 int rv;
11136 if (round == 0) {
[email protected]49639fa2011-12-20 23:22:4111137 rv = trans.Start(&request, callback.callback(), BoundNetLog());
[email protected]044de0642010-06-17 10:42:1511138 } else {
[email protected]49639fa2011-12-20 23:22:4111139 rv = trans.RestartWithAuth(
11140 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1511141 }
11142 if (rv == ERR_IO_PENDING)
11143 rv = callback.WaitForResult();
11144
11145 // Compare results with expected data.
11146 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:5011147 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5511148 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1511149 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
11150 continue;
11151 }
11152 if (round + 1 < test_config.num_auth_rounds) {
11153 EXPECT_FALSE(response->auth_challenge.get() == NULL);
11154 } else {
11155 EXPECT_TRUE(response->auth_challenge.get() == NULL);
11156 }
11157 }
[email protected]e5ae96a2010-04-14 20:12:4511158 }
11159}
11160
[email protected]23e482282013-06-14 16:08:0211161TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1411162 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1411163 HttpAuthHandlerMock::Factory* auth_factory(
11164 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711165 session_deps_.http_auth_handler_factory.reset(auth_factory);
rdsmith82957ad2015-09-16 19:42:0311166 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0711167 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
11168 session_deps_.host_resolver->set_synchronous_mode(true);
[email protected]c871bce92010-07-15 21:51:1411169
11170 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11171 auth_handler->set_connection_based(true);
11172 std::string auth_challenge = "Mock realm=server";
11173 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2411174 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11175 auth_challenge.end());
[email protected]c871bce92010-07-15 21:51:1411176 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
11177 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:0811178 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1411179
[email protected]c871bce92010-07-15 21:51:1411180 int rv = OK;
11181 const HttpResponseInfo* response = NULL;
11182 HttpRequestInfo request;
11183 request.method = "GET";
11184 request.url = origin;
11185 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:2711186
mmenke6b3af6e2015-09-12 02:06:0611187 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1011188
11189 // Use a TCP Socket Pool with only one connection per group. This is used
11190 // to validate that the TCP socket is not released to the pool between
11191 // each round of multi-round authentication.
mmenke6b3af6e2015-09-12 02:06:0611192 HttpNetworkSessionPeer session_peer(session);
[email protected]ab739042011-04-07 15:22:2811193 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:1011194 50, // Max sockets for pool
11195 1, // Max sockets per group
[email protected]bb88e1d32013-05-03 23:11:0711196 session_deps_.host_resolver.get(),
11197 session_deps_.socket_factory.get(),
11198 session_deps_.net_log);
[email protected]831e4a32013-11-14 02:14:4411199 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
11200 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:0211201 mock_pool_manager->SetTransportSocketPool(transport_pool);
dchenge3d1ddc2014-10-15 19:30:5111202 session_peer.SetClientSocketPoolManager(mock_pool_manager.Pass());
[email protected]7ef4cbbb2011-02-06 11:19:1011203
[email protected]262eec82013-03-19 21:01:3611204 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011205 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111206 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1411207
11208 const MockWrite kGet(
11209 "GET / HTTP/1.1\r\n"
11210 "Host: www.example.com\r\n"
11211 "Connection: keep-alive\r\n\r\n");
11212 const MockWrite kGetAuth(
11213 "GET / HTTP/1.1\r\n"
11214 "Host: www.example.com\r\n"
11215 "Connection: keep-alive\r\n"
11216 "Authorization: auth_token\r\n\r\n");
11217
11218 const MockRead kServerChallenge(
11219 "HTTP/1.1 401 Unauthorized\r\n"
11220 "WWW-Authenticate: Mock realm=server\r\n"
11221 "Content-Type: text/html; charset=iso-8859-1\r\n"
11222 "Content-Length: 14\r\n\r\n"
11223 "Unauthorized\r\n");
11224 const MockRead kSuccess(
11225 "HTTP/1.1 200 OK\r\n"
11226 "Content-Type: text/html; charset=iso-8859-1\r\n"
11227 "Content-Length: 3\r\n\r\n"
11228 "Yes");
11229
11230 MockWrite writes[] = {
11231 // First round
11232 kGet,
11233 // Second round
11234 kGetAuth,
11235 // Third round
11236 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3011237 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1011238 kGetAuth,
11239 // Competing request
11240 kGet,
[email protected]c871bce92010-07-15 21:51:1411241 };
11242 MockRead reads[] = {
11243 // First round
11244 kServerChallenge,
11245 // Second round
11246 kServerChallenge,
11247 // Third round
[email protected]eca50e122010-09-11 14:03:3011248 kServerChallenge,
11249 // Fourth round
[email protected]c871bce92010-07-15 21:51:1411250 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1011251 // Competing response
11252 kSuccess,
[email protected]c871bce92010-07-15 21:51:1411253 };
11254 StaticSocketDataProvider data_provider(reads, arraysize(reads),
11255 writes, arraysize(writes));
[email protected]bb88e1d32013-05-03 23:11:0711256 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1411257
thestig9d3bb0c2015-01-24 00:49:5111258 const char kSocketGroup[] = "www.example.com:80";
[email protected]7ef4cbbb2011-02-06 11:19:1011259
11260 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1411261 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111262 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]c871bce92010-07-15 21:51:1411263 if (rv == ERR_IO_PENDING)
11264 rv = callback.WaitForResult();
11265 EXPECT_EQ(OK, rv);
11266 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011267 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411268 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811269 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411270
[email protected]7ef4cbbb2011-02-06 11:19:1011271 // In between rounds, another request comes in for the same domain.
11272 // It should not be able to grab the TCP socket that trans has already
11273 // claimed.
11274 scoped_ptr<HttpTransaction> trans_compete(
[email protected]90499482013-06-01 00:39:5011275 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111276 TestCompletionCallback callback_compete;
11277 rv = trans_compete->Start(
11278 &request, callback_compete.callback(), BoundNetLog());
[email protected]7ef4cbbb2011-02-06 11:19:1011279 EXPECT_EQ(ERR_IO_PENDING, rv);
11280 // callback_compete.WaitForResult at this point would stall forever,
11281 // since the HttpNetworkTransaction does not release the request back to
11282 // the pool until after authentication completes.
11283
11284 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1411285 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111286 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411287 if (rv == ERR_IO_PENDING)
11288 rv = callback.WaitForResult();
11289 EXPECT_EQ(OK, rv);
11290 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011291 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411292 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811293 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411294
[email protected]7ef4cbbb2011-02-06 11:19:1011295 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1411296 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111297 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411298 if (rv == ERR_IO_PENDING)
11299 rv = callback.WaitForResult();
11300 EXPECT_EQ(OK, rv);
11301 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011302 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411303 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811304 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:3011305
[email protected]7ef4cbbb2011-02-06 11:19:1011306 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3011307 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111308 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3011309 if (rv == ERR_IO_PENDING)
11310 rv = callback.WaitForResult();
11311 EXPECT_EQ(OK, rv);
11312 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011313 ASSERT_TRUE(response != NULL);
[email protected]eca50e122010-09-11 14:03:3011314 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811315 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011316
11317 // Read the body since the fourth round was successful. This will also
11318 // release the socket back to the pool.
11319 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
[email protected]90499482013-06-01 00:39:5011320 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011321 if (rv == ERR_IO_PENDING)
11322 rv = callback.WaitForResult();
11323 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011324 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011325 EXPECT_EQ(0, rv);
11326 // There are still 0 idle sockets, since the trans_compete transaction
11327 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:2811328 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011329
11330 // The competing request can now finish. Wait for the headers and then
11331 // read the body.
11332 rv = callback_compete.WaitForResult();
11333 EXPECT_EQ(OK, rv);
[email protected]90499482013-06-01 00:39:5011334 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011335 if (rv == ERR_IO_PENDING)
11336 rv = callback.WaitForResult();
11337 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011338 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011339 EXPECT_EQ(0, rv);
11340
11341 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:2811342 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411343}
11344
[email protected]65041fa2010-05-21 06:56:5311345// This tests the case that a request is issued via http instead of spdy after
11346// npn is negotiated.
[email protected]23e482282013-06-14 16:08:0211347TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
bnc55ff9da2015-08-19 18:42:3511348 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311349 NextProtoVector next_protos;
[email protected]0ce3af82013-07-22 16:17:1611350 next_protos.push_back(kProtoHTTP11);
[email protected]d7599122014-05-24 03:37:2311351 session_deps_.next_protos = next_protos;
11352
[email protected]65041fa2010-05-21 06:56:5311353 HttpRequestInfo request;
11354 request.method = "GET";
bncce36dca22015-04-21 22:11:2311355 request.url = GURL("https://www.example.org/");
[email protected]65041fa2010-05-21 06:56:5311356 request.load_flags = 0;
11357
11358 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311359 MockWrite(
11360 "GET / HTTP/1.1\r\n"
11361 "Host: www.example.org\r\n"
11362 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5311363 };
11364
[email protected]8a0fc822013-06-27 20:52:4311365 std::string alternate_protocol_http_header =
11366 GetAlternateProtocolHttpHeader();
11367
[email protected]65041fa2010-05-21 06:56:5311368 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211369 MockRead("HTTP/1.1 200 OK\r\n"),
11370 MockRead(alternate_protocol_http_header.c_str()),
11371 MockRead("\r\n"),
11372 MockRead("hello world"),
11373 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5311374 };
11375
[email protected]8ddf8322012-02-23 18:08:0611376 SSLSocketDataProvider ssl(ASYNC, OK);
davidben6974bf72015-04-27 17:52:4811377 ssl.SetNextProto(kProtoHTTP11);
[email protected]65041fa2010-05-21 06:56:5311378
[email protected]bb88e1d32013-05-03 23:11:0711379 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5311380
11381 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11382 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0711383 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5311384
[email protected]49639fa2011-12-20 23:22:4111385 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5311386
mmenke6b3af6e2015-09-12 02:06:0611387 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3611388 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011389 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]65041fa2010-05-21 06:56:5311390
[email protected]49639fa2011-12-20 23:22:4111391 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]65041fa2010-05-21 06:56:5311392
11393 EXPECT_EQ(ERR_IO_PENDING, rv);
11394 EXPECT_EQ(OK, callback.WaitForResult());
11395
11396 const HttpResponseInfo* response = trans->GetResponseInfo();
11397 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011398 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]65041fa2010-05-21 06:56:5311399 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11400
11401 std::string response_data;
11402 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11403 EXPECT_EQ("hello world", response_data);
11404
11405 EXPECT_FALSE(response->was_fetched_via_spdy);
11406 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]65041fa2010-05-21 06:56:5311407}
[email protected]26ef6582010-06-24 02:30:4711408
bnc55ff9da2015-08-19 18:42:3511409// Simulate the SSL handshake completing with an NPN negotiation followed by an
11410// immediate server closing of the socket.
11411// Regression test for https://crbug.com/46369.
[email protected]23e482282013-06-14 16:08:0211412TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
bnc55ff9da2015-08-19 18:42:3511413 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311414 session_deps_.next_protos = SpdyNextProtos();
[email protected]26ef6582010-06-24 02:30:4711415
11416 HttpRequestInfo request;
11417 request.method = "GET";
bncce36dca22015-04-21 22:11:2311418 request.url = GURL("https://www.example.org/");
[email protected]26ef6582010-06-24 02:30:4711419 request.load_flags = 0;
11420
[email protected]8ddf8322012-02-23 18:08:0611421 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0211422 ssl.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:0711423 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4711424
[email protected]cdf8f7e72013-05-23 10:56:4611425 scoped_ptr<SpdyFrame> req(
11426 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1311427 MockWrite spdy_writes[] = {CreateMockWrite(*req, 1)};
[email protected]26ef6582010-06-24 02:30:4711428
11429 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0611430 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4711431 };
11432
rch8e6c6c42015-05-01 14:05:1311433 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11434 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711435 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4711436
[email protected]49639fa2011-12-20 23:22:4111437 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4711438
mmenke6b3af6e2015-09-12 02:06:0611439 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3611440 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011441 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]26ef6582010-06-24 02:30:4711442
[email protected]49639fa2011-12-20 23:22:4111443 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]26ef6582010-06-24 02:30:4711444 EXPECT_EQ(ERR_IO_PENDING, rv);
11445 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
[email protected]26ef6582010-06-24 02:30:4711446}
[email protected]65d34382010-07-01 18:12:2611447
[email protected]795cbf82013-07-22 09:37:2711448// A subclass of HttpAuthHandlerMock that records the request URL when
11449// it gets it. This is needed since the auth handler may get destroyed
11450// before we get a chance to query it.
11451class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
11452 public:
11453 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
11454
dchengb03027d2014-10-21 12:00:2011455 ~UrlRecordingHttpAuthHandlerMock() override {}
[email protected]795cbf82013-07-22 09:37:2711456
11457 protected:
dchengb03027d2014-10-21 12:00:2011458 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
11459 const HttpRequestInfo* request,
11460 const CompletionCallback& callback,
11461 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2711462 *url_ = request->url;
11463 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
11464 credentials, request, callback, auth_token);
11465 }
11466
11467 private:
11468 GURL* url_;
11469};
11470
bnc55ff9da2015-08-19 18:42:3511471// This test ensures that the URL passed into the proxy is upgraded to https
11472// when doing an Alternate Protocol upgrade.
[email protected]23e482282013-06-14 16:08:0211473TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
bnc55ff9da2015-08-19 18:42:3511474 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311475 session_deps_.next_protos = SpdyNextProtos();
[email protected]f45c1ee2010-08-03 00:54:3011476
rdsmith82957ad2015-09-16 19:42:0311477 session_deps_.proxy_service =
11478 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5111479 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711480 session_deps_.net_log = &net_log;
[email protected]795cbf82013-07-22 09:37:2711481 GURL request_url;
11482 {
11483 HttpAuthHandlerMock::Factory* auth_factory =
11484 new HttpAuthHandlerMock::Factory();
11485 UrlRecordingHttpAuthHandlerMock* auth_handler =
11486 new UrlRecordingHttpAuthHandlerMock(&request_url);
11487 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
11488 auth_factory->set_do_init_from_challenge(true);
11489 session_deps_.http_auth_handler_factory.reset(auth_factory);
11490 }
[email protected]f45c1ee2010-08-03 00:54:3011491
11492 HttpRequestInfo request;
11493 request.method = "GET";
bncce36dca22015-04-21 22:11:2311494 request.url = GURL("http://www.example.org");
[email protected]f45c1ee2010-08-03 00:54:3011495 request.load_flags = 0;
11496
11497 // First round goes unauthenticated through the proxy.
11498 MockWrite data_writes_1[] = {
bncce36dca22015-04-21 22:11:2311499 MockWrite(
11500 "GET http://www.example.org/ HTTP/1.1\r\n"
11501 "Host: www.example.org\r\n"
11502 "Proxy-Connection: keep-alive\r\n"
11503 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011504 };
11505 MockRead data_reads_1[] = {
[email protected]8ddf8322012-02-23 18:08:0611506 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
bnc33b8cef42014-11-19 17:30:3811507 MockRead("HTTP/1.1 200 OK\r\n"),
11508 MockRead("Alternate-Protocol: 443:"),
11509 MockRead(GetAlternateProtocolFromParam()),
11510 MockRead("\r\n"),
11511 MockRead("Proxy-Connection: close\r\n"),
11512 MockRead("\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011513 };
11514 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
11515 data_writes_1, arraysize(data_writes_1));
11516
bncce36dca22015-04-21 22:11:2311517 // Second round tries to tunnel to www.example.org due to the
[email protected]f45c1ee2010-08-03 00:54:3011518 // Alternate-Protocol announcement in the first round. It fails due
11519 // to a proxy authentication challenge.
bncce36dca22015-04-21 22:11:2311520 // After the failure, a tunnel is established to www.example.org using
[email protected]394816e92010-08-03 07:38:5911521 // Proxy-Authorization headers. There is then a SPDY request round.
11522 //
[email protected]fe3b7dc2012-02-03 19:52:0911523 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
11524 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
11525 // does a Disconnect and Connect on the same socket, rather than trying
11526 // to obtain a new one.
11527 //
[email protected]394816e92010-08-03 07:38:5911528 // NOTE: Originally, the proxy response to the second CONNECT request
11529 // simply returned another 407 so the unit test could skip the SSL connection
11530 // establishment and SPDY framing issues. Alas, the
11531 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:3011532 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:5911533
[email protected]cdf8f7e72013-05-23 10:56:4611534 scoped_ptr<SpdyFrame> req(
11535 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]23e482282013-06-14 16:08:0211536 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11537 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]f45c1ee2010-08-03 00:54:3011538
[email protected]394816e92010-08-03 07:38:5911539 MockWrite data_writes_2[] = {
bncce36dca22015-04-21 22:11:2311540 // First connection attempt without Proxy-Authorization.
rch8e6c6c42015-05-01 14:05:1311541 MockWrite(ASYNC, 0,
11542 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11543 "Host: www.example.org\r\n"
11544 "Proxy-Connection: keep-alive\r\n"
11545 "\r\n"),
[email protected]394816e92010-08-03 07:38:5911546
bncce36dca22015-04-21 22:11:2311547 // Second connection attempt with Proxy-Authorization.
rch8e6c6c42015-05-01 14:05:1311548 MockWrite(ASYNC, 2,
11549 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11550 "Host: www.example.org\r\n"
11551 "Proxy-Connection: keep-alive\r\n"
11552 "Proxy-Authorization: auth_token\r\n"
11553 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011554
bncce36dca22015-04-21 22:11:2311555 // SPDY request
rch8e6c6c42015-05-01 14:05:1311556 CreateMockWrite(*req, 4),
[email protected]f45c1ee2010-08-03 00:54:3011557 };
[email protected]394816e92010-08-03 07:38:5911558 MockRead data_reads_2[] = {
rch8e6c6c42015-05-01 14:05:1311559 // First connection attempt fails
mmenkee71e15332015-10-07 16:39:5411560 MockRead(ASYNC, 1,
11561 "HTTP/1.1 407 Unauthorized\r\n"
11562 "Proxy-Authenticate: Mock\r\n"
11563 "Content-Length: 0\r\n"
11564 "Proxy-Connection: keep-alive\r\n"
11565 "\r\n"),
[email protected]394816e92010-08-03 07:38:5911566
rch8e6c6c42015-05-01 14:05:1311567 // Second connection attempt passes
mmenkee71e15332015-10-07 16:39:5411568 MockRead(ASYNC, 3, "HTTP/1.1 200 Connected\r\n\r\n"),
[email protected]394816e92010-08-03 07:38:5911569
rch8e6c6c42015-05-01 14:05:1311570 // SPDY response
mmenkee71e15332015-10-07 16:39:5411571 CreateMockRead(*resp.get(), 5), CreateMockRead(*data.get(), 6),
rch8e6c6c42015-05-01 14:05:1311572 MockRead(ASYNC, 0, 0, 7),
[email protected]394816e92010-08-03 07:38:5911573 };
rch8e6c6c42015-05-01 14:05:1311574 SequencedSocketData data_2(data_reads_2, arraysize(data_reads_2),
11575 data_writes_2, arraysize(data_writes_2));
[email protected]f45c1ee2010-08-03 00:54:3011576
[email protected]8ddf8322012-02-23 18:08:0611577 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0211578 ssl.SetNextProto(GetParam());
bncce36dca22015-04-21 22:11:2311579 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11580 ASSERT_TRUE(ssl.cert.get());
[email protected]f45c1ee2010-08-03 00:54:3011581
[email protected]d973e99a2012-02-17 21:02:3611582 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5511583 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
11584 NULL, 0, NULL, 0);
11585 hanging_non_alternate_protocol_socket.set_connect_data(
11586 never_finishing_connect);
11587
[email protected]bb88e1d32013-05-03 23:11:0711588 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
11589 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
11590 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11591 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5511592 &hanging_non_alternate_protocol_socket);
mmenke6b3af6e2015-09-12 02:06:0611593 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f45c1ee2010-08-03 00:54:3011594
11595 // First round should work and provide the Alternate-Protocol state.
[email protected]49639fa2011-12-20 23:22:4111596 TestCompletionCallback callback_1;
[email protected]262eec82013-03-19 21:01:3611597 scoped_ptr<HttpTransaction> trans_1(
[email protected]90499482013-06-01 00:39:5011598 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111599 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:3011600 EXPECT_EQ(ERR_IO_PENDING, rv);
11601 EXPECT_EQ(OK, callback_1.WaitForResult());
11602
11603 // Second round should attempt a tunnel connect and get an auth challenge.
[email protected]49639fa2011-12-20 23:22:4111604 TestCompletionCallback callback_2;
[email protected]262eec82013-03-19 21:01:3611605 scoped_ptr<HttpTransaction> trans_2(
[email protected]90499482013-06-01 00:39:5011606 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111607 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:3011608 EXPECT_EQ(ERR_IO_PENDING, rv);
11609 EXPECT_EQ(OK, callback_2.WaitForResult());
11610 const HttpResponseInfo* response = trans_2->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011611 ASSERT_TRUE(response != NULL);
[email protected]f45c1ee2010-08-03 00:54:3011612 ASSERT_FALSE(response->auth_challenge.get() == NULL);
11613
11614 // Restart with auth. Tunnel should work and response received.
[email protected]49639fa2011-12-20 23:22:4111615 TestCompletionCallback callback_3;
11616 rv = trans_2->RestartWithAuth(
11617 AuthCredentials(kFoo, kBar), callback_3.callback());
[email protected]f45c1ee2010-08-03 00:54:3011618 EXPECT_EQ(ERR_IO_PENDING, rv);
11619 EXPECT_EQ(OK, callback_3.WaitForResult());
11620
11621 // After all that work, these two lines (or actually, just the scheme) are
11622 // what this test is all about. Make sure it happens correctly.
[email protected]f45c1ee2010-08-03 00:54:3011623 EXPECT_EQ("https", request_url.scheme());
bncce36dca22015-04-21 22:11:2311624 EXPECT_EQ("www.example.org", request_url.host());
[email protected]f45c1ee2010-08-03 00:54:3011625
[email protected]029c83b62013-01-24 05:28:2011626 LoadTimingInfo load_timing_info;
11627 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
11628 TestLoadTimingNotReusedWithPac(load_timing_info,
11629 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]8e6441ca2010-08-19 05:56:3811630}
11631
11632// Test that if we cancel the transaction as the connection is completing, that
11633// everything tears down correctly.
[email protected]23e482282013-06-14 16:08:0211634TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3811635 // Setup everything about the connection to complete synchronously, so that
11636 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
11637 // for is the callback from the HttpStreamRequest.
11638 // Then cancel the transaction.
11639 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3611640 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3811641 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0611642 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
11643 MockRead(SYNCHRONOUS, "hello world"),
11644 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3811645 };
11646
[email protected]8e6441ca2010-08-19 05:56:3811647 HttpRequestInfo request;
11648 request.method = "GET";
bncce36dca22015-04-21 22:11:2311649 request.url = GURL("http://www.example.org/");
[email protected]8e6441ca2010-08-19 05:56:3811650 request.load_flags = 0;
11651
[email protected]bb88e1d32013-05-03 23:11:0711652 session_deps_.host_resolver->set_synchronous_mode(true);
mmenke6b3af6e2015-09-12 02:06:0611653 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:2711654 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4111655 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:2711656
[email protected]8e6441ca2010-08-19 05:56:3811657 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
11658 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0711659 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3811660
[email protected]49639fa2011-12-20 23:22:4111661 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3811662
vishal.b62985ca92015-04-17 08:45:5111663 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4111664 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]8e6441ca2010-08-19 05:56:3811665 EXPECT_EQ(ERR_IO_PENDING, rv);
11666 trans.reset(); // Cancel the transaction here.
11667
[email protected]2da659e2013-05-23 20:51:3411668 base::MessageLoop::current()->RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3011669}
11670
[email protected]ecab6e052014-05-16 14:58:1211671// Test that if a transaction is cancelled after receiving the headers, the
11672// stream is drained properly and added back to the socket pool. The main
11673// purpose of this test is to make sure that an HttpStreamParser can be read
11674// from after the HttpNetworkTransaction and the objects it owns have been
11675// deleted.
11676// See http://crbug.com/368418
11677TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
11678 MockRead data_reads[] = {
11679 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
11680 MockRead(ASYNC, "Content-Length: 2\r\n"),
11681 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
11682 MockRead(ASYNC, "1"),
11683 // 2 async reads are necessary to trigger a ReadResponseBody call after the
11684 // HttpNetworkTransaction has been deleted.
11685 MockRead(ASYNC, "2"),
11686 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
11687 };
11688 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
11689 session_deps_.socket_factory->AddSocketDataProvider(&data);
11690
mmenke6b3af6e2015-09-12 02:06:0611691 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1211692
11693 {
11694 HttpRequestInfo request;
11695 request.method = "GET";
bncce36dca22015-04-21 22:11:2311696 request.url = GURL("http://www.example.org/");
[email protected]ecab6e052014-05-16 14:58:1211697 request.load_flags = 0;
11698
dcheng48459ac22014-08-26 00:46:4111699 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1211700 TestCompletionCallback callback;
11701
11702 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
11703 EXPECT_EQ(ERR_IO_PENDING, rv);
11704 callback.WaitForResult();
11705
11706 const HttpResponseInfo* response = trans.GetResponseInfo();
11707 ASSERT_TRUE(response != NULL);
11708 EXPECT_TRUE(response->headers.get() != NULL);
11709 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11710
11711 // The transaction and HttpRequestInfo are deleted.
11712 }
11713
11714 // Let the HttpResponseBodyDrainer drain the socket.
11715 base::MessageLoop::current()->RunUntilIdle();
11716
11717 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4111718 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1211719}
11720
[email protected]76a505b2010-08-25 06:23:0011721// Test a basic GET request through a proxy.
[email protected]23e482282013-06-14 16:08:0211722TEST_P(HttpNetworkTransactionTest, ProxyGet) {
rdsmith82957ad2015-09-16 19:42:0311723 session_deps_.proxy_service =
11724 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5111725 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711726 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:0611727 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0011728
[email protected]76a505b2010-08-25 06:23:0011729 HttpRequestInfo request;
11730 request.method = "GET";
bncce36dca22015-04-21 22:11:2311731 request.url = GURL("http://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0011732
11733 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311734 MockWrite(
11735 "GET http://www.example.org/ HTTP/1.1\r\n"
11736 "Host: www.example.org\r\n"
11737 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0011738 };
11739
11740 MockRead data_reads1[] = {
11741 MockRead("HTTP/1.1 200 OK\r\n"),
11742 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11743 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611744 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0011745 };
11746
11747 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
11748 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0711749 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0011750
[email protected]49639fa2011-12-20 23:22:4111751 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0011752
[email protected]262eec82013-03-19 21:01:3611753 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011754 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]597a1ab2014-06-26 08:12:2711755 BeforeProxyHeadersSentHandler proxy_headers_handler;
11756 trans->SetBeforeProxyHeadersSentCallback(
11757 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
11758 base::Unretained(&proxy_headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5011759
[email protected]49639fa2011-12-20 23:22:4111760 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0011761 EXPECT_EQ(ERR_IO_PENDING, rv);
11762
11763 rv = callback1.WaitForResult();
11764 EXPECT_EQ(OK, rv);
11765
11766 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011767 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:0011768
11769 EXPECT_TRUE(response->headers->IsKeepAlive());
11770 EXPECT_EQ(200, response->headers->response_code());
11771 EXPECT_EQ(100, response->headers->GetContentLength());
11772 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1511773 EXPECT_TRUE(
11774 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
[email protected]597a1ab2014-06-26 08:12:2711775 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
11776 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0011777 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2011778
11779 LoadTimingInfo load_timing_info;
11780 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11781 TestLoadTimingNotReusedWithPac(load_timing_info,
11782 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0011783}
11784
11785// Test a basic HTTPS GET request through a proxy.
[email protected]23e482282013-06-14 16:08:0211786TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
rdsmith82957ad2015-09-16 19:42:0311787 session_deps_.proxy_service =
11788 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5111789 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711790 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:0611791 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0011792
[email protected]76a505b2010-08-25 06:23:0011793 HttpRequestInfo request;
11794 request.method = "GET";
bncce36dca22015-04-21 22:11:2311795 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0011796
11797 // Since we have proxy, should try to establish tunnel.
11798 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311799 MockWrite(
11800 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11801 "Host: www.example.org\r\n"
11802 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0011803
bncce36dca22015-04-21 22:11:2311804 MockWrite(
11805 "GET / HTTP/1.1\r\n"
11806 "Host: www.example.org\r\n"
11807 "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 Connection Established\r\n\r\n"),
11812
11813 MockRead("HTTP/1.1 200 OK\r\n"),
11814 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11815 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611816 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0011817 };
11818
11819 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
11820 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0711821 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0611822 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711823 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0011824
[email protected]49639fa2011-12-20 23:22:4111825 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0011826
[email protected]262eec82013-03-19 21:01:3611827 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011828 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[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);
mmenke43758e62015-05-04 21:09:4611835 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4011836 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0011837 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4011838 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0011839 NetLog::PHASE_NONE);
11840 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4011841 entries, pos,
[email protected]76a505b2010-08-25 06:23:0011842 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11843 NetLog::PHASE_NONE);
11844
11845 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011846 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:0011847
11848 EXPECT_TRUE(response->headers->IsKeepAlive());
11849 EXPECT_EQ(200, response->headers->response_code());
11850 EXPECT_EQ(100, response->headers->GetContentLength());
11851 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
11852 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1511853 EXPECT_TRUE(
11854 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
[email protected]029c83b62013-01-24 05:28:2011855
11856 LoadTimingInfo load_timing_info;
11857 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11858 TestLoadTimingNotReusedWithPac(load_timing_info,
11859 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0011860}
11861
11862// Test a basic HTTPS GET request through a proxy, but the server hangs up
11863// while establishing the tunnel.
[email protected]23e482282013-06-14 16:08:0211864TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
rdsmith82957ad2015-09-16 19:42:0311865 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:5111866 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0711867 session_deps_.net_log = log.bound().net_log();
mmenke6b3af6e2015-09-12 02:06:0611868 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0011869
[email protected]76a505b2010-08-25 06:23:0011870 HttpRequestInfo request;
11871 request.method = "GET";
bncce36dca22015-04-21 22:11:2311872 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0011873
11874 // Since we have proxy, should try to establish tunnel.
11875 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311876 MockWrite(
11877 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11878 "Host: www.example.org\r\n"
11879 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0011880
bncce36dca22015-04-21 22:11:2311881 MockWrite(
11882 "GET / HTTP/1.1\r\n"
11883 "Host: www.example.org\r\n"
11884 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0011885 };
11886
11887 MockRead data_reads1[] = {
[email protected]8ddf8322012-02-23 18:08:0611888 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]76a505b2010-08-25 06:23:0011889 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611890 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0011891 };
11892
11893 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
11894 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0711895 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0611896 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711897 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0011898
[email protected]49639fa2011-12-20 23:22:4111899 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0011900
[email protected]262eec82013-03-19 21:01:3611901 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011902 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:5011903
[email protected]49639fa2011-12-20 23:22:4111904 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0011905 EXPECT_EQ(ERR_IO_PENDING, rv);
11906
11907 rv = callback1.WaitForResult();
11908 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
mmenke43758e62015-05-04 21:09:4611909 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4011910 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0011911 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4011912 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0011913 NetLog::PHASE_NONE);
11914 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4011915 entries, pos,
[email protected]76a505b2010-08-25 06:23:0011916 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
11917 NetLog::PHASE_NONE);
11918}
11919
[email protected]749eefa82010-09-13 22:14:0311920// Test for crbug.com/55424.
[email protected]23e482282013-06-14 16:08:0211921TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
[email protected]cdf8f7e72013-05-23 10:56:4611922 scoped_ptr<SpdyFrame> req(
bncce36dca22015-04-21 22:11:2311923 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rch8e6c6c42015-05-01 14:05:1311924 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]749eefa82010-09-13 22:14:0311925
[email protected]23e482282013-06-14 16:08:0211926 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11927 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0311928 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1311929 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0311930 };
11931
rch8e6c6c42015-05-01 14:05:1311932 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11933 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711934 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0311935
[email protected]8ddf8322012-02-23 18:08:0611936 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0211937 ssl.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:0711938 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0311939
mmenke6b3af6e2015-09-12 02:06:0611940 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0311941
11942 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2311943 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4011944 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5311945 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2711946 base::WeakPtr<SpdySession> spdy_session =
mmenke6b3af6e2015-09-12 02:06:0611947 CreateInsecureSpdySession(session, key, BoundNetLog());
[email protected]749eefa82010-09-13 22:14:0311948
11949 HttpRequestInfo request;
11950 request.method = "GET";
bncce36dca22015-04-21 22:11:2311951 request.url = GURL("https://www.example.org/");
[email protected]749eefa82010-09-13 22:14:0311952 request.load_flags = 0;
11953
11954 // This is the important line that marks this as a preconnect.
11955 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
11956
[email protected]262eec82013-03-19 21:01:3611957 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011958 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]749eefa82010-09-13 22:14:0311959
[email protected]41d64e82013-07-03 22:44:2611960 TestCompletionCallback callback;
[email protected]49639fa2011-12-20 23:22:4111961 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]749eefa82010-09-13 22:14:0311962 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4111963 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]749eefa82010-09-13 22:14:0311964}
11965
[email protected]73b8dd222010-11-11 19:55:2411966// Given a net error, cause that error to be returned from the first Write()
11967// call and verify that the HttpTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0211968void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0711969 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2911970 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2711971 request_info.url = GURL("https://www.example.com/");
11972 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2911973 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2711974
[email protected]8ddf8322012-02-23 18:08:0611975 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2911976 MockWrite data_writes[] = {
11977 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2411978 };
ttuttle859dc7a2015-04-23 19:42:2911979 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0711980 session_deps_.socket_factory->AddSocketDataProvider(&data);
11981 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2411982
mmenke6b3af6e2015-09-12 02:06:0611983 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3611984 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011985 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]73b8dd222010-11-11 19:55:2411986
[email protected]49639fa2011-12-20 23:22:4111987 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2911988 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
11989 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2411990 rv = callback.WaitForResult();
11991 ASSERT_EQ(error, rv);
11992}
11993
[email protected]23e482282013-06-14 16:08:0211994TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2411995 // Just check a grab bag of cert errors.
11996 static const int kErrors[] = {
11997 ERR_CERT_COMMON_NAME_INVALID,
11998 ERR_CERT_AUTHORITY_INVALID,
11999 ERR_CERT_DATE_INVALID,
12000 };
12001 for (size_t i = 0; i < arraysize(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0612002 CheckErrorIsPassedBack(kErrors[i], ASYNC);
12003 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2412004 }
12005}
12006
[email protected]bd0b6772011-01-11 19:59:3012007// Ensure that a client certificate is removed from the SSL client auth
12008// cache when:
12009// 1) No proxy is involved.
12010// 2) TLS False Start is disabled.
12011// 3) The initial TLS handshake requests a client certificate.
12012// 4) The client supplies an invalid/unacceptable certificate.
[email protected]23e482282013-06-14 16:08:0212013TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2312014 ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912015 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712016 request_info.url = GURL("https://www.example.com/");
12017 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912018 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712019
[email protected]bd0b6772011-01-11 19:59:3012020 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112021 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012022
12023 // [ssl_]data1 contains the data for the first SSL handshake. When a
12024 // CertificateRequest is received for the first time, the handshake will
12025 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2912026 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012027 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712028 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912029 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712030 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012031
12032 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
12033 // False Start is not being used, the result of the SSL handshake will be
12034 // returned as part of the SSLClientSocket::Connect() call. This test
12035 // matches the result of a server sending a handshake_failure alert,
12036 // rather than a Finished message, because it requires a client
12037 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2912038 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012039 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712040 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912041 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712042 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012043
12044 // [ssl_]data3 contains the data for the third SSL handshake. When a
12045 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212046 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
12047 // connection was attempted with TLSv1.2. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3012048 // of the HttpNetworkTransaction. Because this test failure is due to
12049 // requiring a client certificate, this fallback handshake should also
12050 // fail.
ttuttle859dc7a2015-04-23 19:42:2912051 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012052 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712053 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912054 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712055 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012056
[email protected]80c75f682012-05-26 16:22:1712057 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
12058 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212059 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
12060 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1712061 // of the HttpNetworkTransaction. Because this test failure is due to
12062 // requiring a client certificate, this fallback handshake should also
12063 // fail.
ttuttle859dc7a2015-04-23 19:42:2912064 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1712065 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712066 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912067 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712068 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712069
mmenke6b3af6e2015-09-12 02:06:0612070 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612071 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012072 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012073
[email protected]bd0b6772011-01-11 19:59:3012074 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4112075 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912076 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12077 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012078
12079 // Complete the SSL handshake, which should abort due to requiring a
12080 // client certificate.
12081 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912082 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]bd0b6772011-01-11 19:59:3012083
12084 // Indicate that no certificate should be supplied. From the perspective
12085 // of SSLClientCertCache, NULL is just as meaningful as a real
12086 // certificate, so this is the same as supply a
12087 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:4112088 rv = trans->RestartWithCertificate(NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912089 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012090
12091 // Ensure the certificate was added to the client auth cache before
12092 // allowing the connection to continue restarting.
12093 scoped_refptr<X509Certificate> client_cert;
[email protected]791879c2013-12-17 07:22:4112094 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
12095 HostPortPair("www.example.com", 443), &client_cert));
[email protected]bd0b6772011-01-11 19:59:3012096 ASSERT_EQ(NULL, client_cert.get());
12097
12098 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712099 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12100 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012101 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912102 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
[email protected]bd0b6772011-01-11 19:59:3012103
12104 // Ensure that the client certificate is removed from the cache on a
12105 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112106 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
12107 HostPortPair("www.example.com", 443), &client_cert));
[email protected]bd0b6772011-01-11 19:59:3012108}
12109
12110// Ensure that a client certificate is removed from the SSL client auth
12111// cache when:
12112// 1) No proxy is involved.
12113// 2) TLS False Start is enabled.
12114// 3) The initial TLS handshake requests a client certificate.
12115// 4) The client supplies an invalid/unacceptable certificate.
[email protected]23e482282013-06-14 16:08:0212116TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2312117 ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912118 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712119 request_info.url = GURL("https://www.example.com/");
12120 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912121 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712122
[email protected]bd0b6772011-01-11 19:59:3012123 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112124 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012125
12126 // When TLS False Start is used, SSLClientSocket::Connect() calls will
12127 // return successfully after reading up to the peer's Certificate message.
12128 // This is to allow the caller to call SSLClientSocket::Write(), which can
12129 // enqueue application data to be sent in the same packet as the
12130 // ChangeCipherSpec and Finished messages.
12131 // The actual handshake will be finished when SSLClientSocket::Read() is
12132 // called, which expects to process the peer's ChangeCipherSpec and
12133 // Finished messages. If there was an error negotiating with the peer,
12134 // such as due to the peer requiring a client certificate when none was
12135 // supplied, the alert sent by the peer won't be processed until Read() is
12136 // called.
12137
12138 // Like the non-False Start case, when a client certificate is requested by
12139 // the peer, the handshake is aborted during the Connect() call.
12140 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2912141 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012142 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712143 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912144 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712145 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012146
12147 // When a client certificate is supplied, Connect() will not be aborted
12148 // when the peer requests the certificate. Instead, the handshake will
12149 // artificially succeed, allowing the caller to write the HTTP request to
12150 // the socket. The handshake messages are not processed until Read() is
12151 // called, which then detects that the handshake was aborted, due to the
12152 // peer sending a handshake_failure because it requires a client
12153 // certificate.
ttuttle859dc7a2015-04-23 19:42:2912154 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012155 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712156 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912157 MockRead data2_reads[] = {
12158 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3012159 };
ttuttle859dc7a2015-04-23 19:42:2912160 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712161 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012162
12163 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1712164 // the data for the SSL handshake once the TLSv1.1 connection falls back to
12165 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912166 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012167 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712168 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912169 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712170 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012171
[email protected]80c75f682012-05-26 16:22:1712172 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
12173 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912174 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1712175 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712176 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912177 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712178 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712179
[email protected]7799de12013-05-30 05:52:5112180 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2912181 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5112182 ssl_data5.cert_request_info = cert_request.get();
12183 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
ttuttle859dc7a2015-04-23 19:42:2912184 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]7799de12013-05-30 05:52:5112185 session_deps_.socket_factory->AddSocketDataProvider(&data5);
12186
mmenke6b3af6e2015-09-12 02:06:0612187 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612188 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012189 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012190
[email protected]bd0b6772011-01-11 19:59:3012191 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4112192 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912193 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12194 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012195
12196 // Complete the SSL handshake, which should abort due to requiring a
12197 // client certificate.
12198 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912199 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]bd0b6772011-01-11 19:59:3012200
12201 // Indicate that no certificate should be supplied. From the perspective
12202 // of SSLClientCertCache, NULL is just as meaningful as a real
12203 // certificate, so this is the same as supply a
12204 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:4112205 rv = trans->RestartWithCertificate(NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912206 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012207
12208 // Ensure the certificate was added to the client auth cache before
12209 // allowing the connection to continue restarting.
12210 scoped_refptr<X509Certificate> client_cert;
[email protected]791879c2013-12-17 07:22:4112211 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
12212 HostPortPair("www.example.com", 443), &client_cert));
[email protected]bd0b6772011-01-11 19:59:3012213 ASSERT_EQ(NULL, client_cert.get());
12214
[email protected]bd0b6772011-01-11 19:59:3012215 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712216 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12217 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012218 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912219 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
[email protected]bd0b6772011-01-11 19:59:3012220
12221 // Ensure that the client certificate is removed from the cache on a
12222 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112223 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
12224 HostPortPair("www.example.com", 443), &client_cert));
[email protected]bd0b6772011-01-11 19:59:3012225}
12226
[email protected]8c405132011-01-11 22:03:1812227// Ensure that a client certificate is removed from the SSL client auth
12228// cache when:
12229// 1) An HTTPS proxy is involved.
12230// 3) The HTTPS proxy requests a client certificate.
12231// 4) The client supplies an invalid/unacceptable certificate for the
12232// proxy.
12233// The test is repeated twice, first for connecting to an HTTPS endpoint,
12234// then for connecting to an HTTP endpoint.
[email protected]23e482282013-06-14 16:08:0212235TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
rdsmith82957ad2015-09-16 19:42:0312236 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:5112237 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712238 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1812239
12240 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112241 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1812242
12243 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
12244 // [ssl_]data[1-3]. Rather than represending the endpoint
12245 // (www.example.com:443), they represent failures with the HTTPS proxy
12246 // (proxy:70).
ttuttle859dc7a2015-04-23 19:42:2912247 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8c405132011-01-11 22:03:1812248 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712249 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912250 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712251 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1812252
ttuttle859dc7a2015-04-23 19:42:2912253 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812254 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712255 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912256 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712257 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8c405132011-01-11 22:03:1812258
[email protected]80c75f682012-05-26 16:22:1712259 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
12260#if 0
ttuttle859dc7a2015-04-23 19:42:2912261 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812262 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712263 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912264 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712265 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]80c75f682012-05-26 16:22:1712266#endif
[email protected]8c405132011-01-11 22:03:1812267
ttuttle859dc7a2015-04-23 19:42:2912268 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1812269 requests[0].url = GURL("https://www.example.com/");
12270 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912271 requests[0].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812272
12273 requests[1].url = GURL("http://www.example.com/");
12274 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912275 requests[1].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812276
12277 for (size_t i = 0; i < arraysize(requests); ++i) {
[email protected]bb88e1d32013-05-03 23:11:0712278 session_deps_.socket_factory->ResetNextMockIndexes();
mmenke6b3af6e2015-09-12 02:06:0612279 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c405132011-01-11 22:03:1812280 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5012281 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c405132011-01-11 22:03:1812282
12283 // Begin the SSL handshake with the proxy.
[email protected]49639fa2011-12-20 23:22:4112284 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912285 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
12286 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]8c405132011-01-11 22:03:1812287
12288 // Complete the SSL handshake, which should abort due to requiring a
12289 // client certificate.
12290 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912291 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]8c405132011-01-11 22:03:1812292
12293 // Indicate that no certificate should be supplied. From the perspective
12294 // of SSLClientCertCache, NULL is just as meaningful as a real
12295 // certificate, so this is the same as supply a
12296 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:4112297 rv = trans->RestartWithCertificate(NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912298 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]8c405132011-01-11 22:03:1812299
12300 // Ensure the certificate was added to the client auth cache before
12301 // allowing the connection to continue restarting.
12302 scoped_refptr<X509Certificate> client_cert;
[email protected]791879c2013-12-17 07:22:4112303 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
12304 HostPortPair("proxy", 70), &client_cert));
[email protected]8c405132011-01-11 22:03:1812305 ASSERT_EQ(NULL, client_cert.get());
12306 // Ensure the certificate was NOT cached for the endpoint. This only
12307 // applies to HTTPS requests, but is fine to check for HTTP requests.
[email protected]791879c2013-12-17 07:22:4112308 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
12309 HostPortPair("www.example.com", 443), &client_cert));
[email protected]8c405132011-01-11 22:03:1812310
12311 // Restart the handshake. This will consume ssl_data2, which fails, and
12312 // then consume ssl_data3, which should also fail. The result code is
12313 // checked against what ssl_data3 should return.
12314 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912315 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]8c405132011-01-11 22:03:1812316
12317 // Now that the new handshake has failed, ensure that the client
12318 // certificate was removed from the client auth cache.
[email protected]791879c2013-12-17 07:22:4112319 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
12320 HostPortPair("proxy", 70), &client_cert));
12321 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
12322 HostPortPair("www.example.com", 443), &client_cert));
[email protected]8c405132011-01-11 22:03:1812323 }
12324}
12325
mmenke5c642132015-06-02 16:05:1312326TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
bnc55ff9da2015-08-19 18:42:3512327 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312328 session_deps_.next_protos = SpdyNextProtos();
[email protected]e3ceb682011-06-28 23:55:4612329
12330 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712331 session_deps_.host_resolver.reset(new MockCachingHostResolver());
mmenke6b3af6e2015-09-12 02:06:0612332 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2612333 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12334 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4612335
[email protected]8ddf8322012-02-23 18:08:0612336 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0212337 ssl.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:0712338 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4612339
[email protected]cdf8f7e72013-05-23 10:56:4612340 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2312341 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
[email protected]cdf8f7e72013-05-23 10:56:4612342 scoped_ptr<SpdyFrame> host2_req(
12343 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4612344 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312345 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4612346 };
[email protected]23e482282013-06-14 16:08:0212347 scoped_ptr<SpdyFrame> host1_resp(
12348 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12349 scoped_ptr<SpdyFrame> host1_resp_body(
12350 spdy_util_.ConstructSpdyBodyFrame(1, true));
12351 scoped_ptr<SpdyFrame> host2_resp(
12352 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12353 scoped_ptr<SpdyFrame> host2_resp_body(
12354 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4612355 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312356 CreateMockRead(*host1_resp, 1),
12357 CreateMockRead(*host1_resp_body, 2),
12358 CreateMockRead(*host2_resp, 4),
12359 CreateMockRead(*host2_resp_body, 5),
12360 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4612361 };
12362
[email protected]d2b5f092012-06-08 23:55:0212363 IPAddressNumber ip;
12364 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
12365 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12366 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312367 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12368 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712369 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4612370
[email protected]aa22b242011-11-16 18:58:2912371 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4612372 HttpRequestInfo request1;
12373 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312374 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4612375 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012376 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612377
[email protected]49639fa2011-12-20 23:22:4112378 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612379 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112380 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612381
12382 const HttpResponseInfo* response = trans1.GetResponseInfo();
12383 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012384 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]e3ceb682011-06-28 23:55:4612385 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12386
12387 std::string response_data;
12388 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12389 EXPECT_EQ("hello!", response_data);
12390
12391 // Preload www.gmail.com into HostCache.
12392 HostPortPair host_port("www.gmail.com", 443);
[email protected]5109c1952013-08-20 18:44:1012393 HostResolver::RequestInfo resolve_info(host_port);
[email protected]e3ceb682011-06-28 23:55:4612394 AddressList ignored;
[email protected]5109c1952013-08-20 18:44:1012395 rv = session_deps_.host_resolver->Resolve(resolve_info,
12396 DEFAULT_PRIORITY,
12397 &ignored,
12398 callback.callback(),
12399 NULL,
12400 BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:4712401 EXPECT_EQ(ERR_IO_PENDING, rv);
12402 rv = callback.WaitForResult();
12403 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:4612404
12405 HttpRequestInfo request2;
12406 request2.method = "GET";
12407 request2.url = GURL("https://www.gmail.com/");
12408 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012409 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612410
[email protected]49639fa2011-12-20 23:22:4112411 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612412 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112413 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612414
12415 response = trans2.GetResponseInfo();
12416 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012417 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]e3ceb682011-06-28 23:55:4612418 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12419 EXPECT_TRUE(response->was_fetched_via_spdy);
12420 EXPECT_TRUE(response->was_npn_negotiated);
12421 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12422 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4612423}
12424
[email protected]23e482282013-06-14 16:08:0212425TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
bnc55ff9da2015-08-19 18:42:3512426 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312427 session_deps_.next_protos = SpdyNextProtos();
[email protected]d2b5f092012-06-08 23:55:0212428
12429 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712430 session_deps_.host_resolver.reset(new MockCachingHostResolver());
mmenke6b3af6e2015-09-12 02:06:0612431 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0212432 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12433 pool_peer.DisableDomainAuthenticationVerification();
12434
12435 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0212436 ssl.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:0712437 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]d2b5f092012-06-08 23:55:0212438
[email protected]cdf8f7e72013-05-23 10:56:4612439 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2312440 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
[email protected]cdf8f7e72013-05-23 10:56:4612441 scoped_ptr<SpdyFrame> host2_req(
12442 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0212443 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312444 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0212445 };
[email protected]23e482282013-06-14 16:08:0212446 scoped_ptr<SpdyFrame> host1_resp(
12447 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12448 scoped_ptr<SpdyFrame> host1_resp_body(
12449 spdy_util_.ConstructSpdyBodyFrame(1, true));
12450 scoped_ptr<SpdyFrame> host2_resp(
12451 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12452 scoped_ptr<SpdyFrame> host2_resp_body(
12453 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0212454 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312455 CreateMockRead(*host1_resp, 1),
12456 CreateMockRead(*host1_resp_body, 2),
12457 CreateMockRead(*host2_resp, 4),
12458 CreateMockRead(*host2_resp_body, 5),
12459 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0212460 };
12461
12462 IPAddressNumber ip;
12463 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
12464 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12465 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312466 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12467 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712468 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0212469
12470 TestCompletionCallback callback;
12471 HttpRequestInfo request1;
12472 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312473 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0212474 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012475 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0212476
12477 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
12478 EXPECT_EQ(ERR_IO_PENDING, rv);
12479 EXPECT_EQ(OK, callback.WaitForResult());
12480
12481 const HttpResponseInfo* response = trans1.GetResponseInfo();
12482 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012483 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]d2b5f092012-06-08 23:55:0212484 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12485
12486 std::string response_data;
12487 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12488 EXPECT_EQ("hello!", response_data);
12489
12490 HttpRequestInfo request2;
12491 request2.method = "GET";
12492 request2.url = GURL("https://www.gmail.com/");
12493 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012494 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0212495
12496 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
12497 EXPECT_EQ(ERR_IO_PENDING, rv);
12498 EXPECT_EQ(OK, callback.WaitForResult());
12499
12500 response = trans2.GetResponseInfo();
12501 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012502 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]d2b5f092012-06-08 23:55:0212503 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12504 EXPECT_TRUE(response->was_fetched_via_spdy);
12505 EXPECT_TRUE(response->was_npn_negotiated);
12506 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12507 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0212508}
12509
ttuttle859dc7a2015-04-23 19:42:2912510class OneTimeCachingHostResolver : public HostResolver {
[email protected]e3ceb682011-06-28 23:55:4612511 public:
12512 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
12513 : host_port_(host_port) {}
dchengb03027d2014-10-21 12:00:2012514 ~OneTimeCachingHostResolver() override {}
[email protected]e3ceb682011-06-28 23:55:4612515
12516 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
12517
12518 // HostResolver methods:
dchengb03027d2014-10-21 12:00:2012519 int Resolve(const RequestInfo& info,
12520 RequestPriority priority,
12521 AddressList* addresses,
12522 const CompletionCallback& callback,
12523 RequestHandle* out_req,
12524 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4012525 return host_resolver_.Resolve(
[email protected]5109c1952013-08-20 18:44:1012526 info, priority, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:4012527 }
12528
dchengb03027d2014-10-21 12:00:2012529 int ResolveFromCache(const RequestInfo& info,
12530 AddressList* addresses,
12531 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4012532 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
12533 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]98e1cd012011-11-08 15:33:0912534 host_resolver_.GetHostCache()->clear();
[email protected]e3ceb682011-06-28 23:55:4612535 return rv;
12536 }
12537
dchengb03027d2014-10-21 12:00:2012538 void CancelRequest(RequestHandle req) override {
[email protected]e3ceb682011-06-28 23:55:4612539 host_resolver_.CancelRequest(req);
12540 }
12541
[email protected]46da33be2011-07-19 21:58:0412542 MockCachingHostResolver* GetMockHostResolver() {
12543 return &host_resolver_;
12544 }
12545
[email protected]e3ceb682011-06-28 23:55:4612546 private:
12547 MockCachingHostResolver host_resolver_;
12548 const HostPortPair host_port_;
12549};
12550
mmenke5c642132015-06-02 16:05:1312551TEST_P(HttpNetworkTransactionTest,
12552 UseIPConnectionPoolingWithHostCacheExpiration) {
bnc55ff9da2015-08-19 18:42:3512553 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312554 session_deps_.next_protos = SpdyNextProtos();
[email protected]e3ceb682011-06-28 23:55:4612555
12556 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
[email protected]e3ceb682011-06-28 23:55:4612557 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
[email protected]c6bf8152012-12-02 07:43:3412558 HttpNetworkSession::Params params =
[email protected]bb88e1d32013-05-03 23:11:0712559 SpdySessionDependencies::CreateSessionParams(&session_deps_);
[email protected]e3ceb682011-06-28 23:55:4612560 params.host_resolver = &host_resolver;
mmenke6b3af6e2015-09-12 02:06:0612561 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2612562 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12563 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4612564
[email protected]8ddf8322012-02-23 18:08:0612565 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0212566 ssl.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:0712567 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4612568
[email protected]cdf8f7e72013-05-23 10:56:4612569 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2312570 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
[email protected]cdf8f7e72013-05-23 10:56:4612571 scoped_ptr<SpdyFrame> host2_req(
12572 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4612573 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312574 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4612575 };
[email protected]23e482282013-06-14 16:08:0212576 scoped_ptr<SpdyFrame> host1_resp(
12577 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12578 scoped_ptr<SpdyFrame> host1_resp_body(
12579 spdy_util_.ConstructSpdyBodyFrame(1, true));
12580 scoped_ptr<SpdyFrame> host2_resp(
12581 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12582 scoped_ptr<SpdyFrame> host2_resp_body(
12583 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4612584 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312585 CreateMockRead(*host1_resp, 1),
12586 CreateMockRead(*host1_resp_body, 2),
12587 CreateMockRead(*host2_resp, 4),
12588 CreateMockRead(*host2_resp_body, 5),
12589 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4612590 };
12591
[email protected]d2b5f092012-06-08 23:55:0212592 IPAddressNumber ip;
12593 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
12594 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12595 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312596 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12597 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712598 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4612599
[email protected]aa22b242011-11-16 18:58:2912600 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4612601 HttpRequestInfo request1;
12602 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312603 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4612604 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012605 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612606
[email protected]49639fa2011-12-20 23:22:4112607 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612608 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112609 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612610
12611 const HttpResponseInfo* response = trans1.GetResponseInfo();
12612 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012613 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]e3ceb682011-06-28 23:55:4612614 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12615
12616 std::string response_data;
12617 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12618 EXPECT_EQ("hello!", response_data);
12619
12620 // Preload cache entries into HostCache.
[email protected]5109c1952013-08-20 18:44:1012621 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
[email protected]e3ceb682011-06-28 23:55:4612622 AddressList ignored;
[email protected]5109c1952013-08-20 18:44:1012623 rv = host_resolver.Resolve(resolve_info,
12624 DEFAULT_PRIORITY,
12625 &ignored,
12626 callback.callback(),
12627 NULL,
12628 BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:4712629 EXPECT_EQ(ERR_IO_PENDING, rv);
12630 rv = callback.WaitForResult();
12631 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:4612632
12633 HttpRequestInfo request2;
12634 request2.method = "GET";
12635 request2.url = GURL("https://www.gmail.com/");
12636 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012637 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612638
[email protected]49639fa2011-12-20 23:22:4112639 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612640 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112641 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612642
12643 response = trans2.GetResponseInfo();
12644 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012645 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]e3ceb682011-06-28 23:55:4612646 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12647 EXPECT_TRUE(response->was_fetched_via_spdy);
12648 EXPECT_TRUE(response->was_npn_negotiated);
12649 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12650 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4612651}
12652
[email protected]23e482282013-06-14 16:08:0212653TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2312654 const std::string https_url = "https://www.example.org:8080/";
12655 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0412656
12657 // SPDY GET for HTTPS URL
[email protected]cdf8f7e72013-05-23 10:56:4612658 scoped_ptr<SpdyFrame> req1(
12659 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0412660
12661 MockWrite writes1[] = {
12662 CreateMockWrite(*req1, 0),
12663 };
12664
[email protected]23e482282013-06-14 16:08:0212665 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12666 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]8450d722012-07-02 19:14:0412667 MockRead reads1[] = {
12668 CreateMockRead(*resp1, 1),
12669 CreateMockRead(*body1, 2),
12670 MockRead(ASYNC, ERR_IO_PENDING, 3)
12671 };
12672
rch8e6c6c42015-05-01 14:05:1312673 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
12674 arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0412675 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5712676 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0412677
12678 // HTTP GET for the HTTP URL
12679 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1312680 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3412681 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2312682 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3412683 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0412684 };
12685
12686 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1312687 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
12688 MockRead(ASYNC, 2, "hello"),
12689 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0412690 };
12691
rch8e6c6c42015-05-01 14:05:1312692 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
12693 arraysize(writes2));
[email protected]8450d722012-07-02 19:14:0412694
[email protected]8450d722012-07-02 19:14:0412695 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0212696 ssl.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:0712697 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12698 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12699 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0412700
mmenke6b3af6e2015-09-12 02:06:0612701 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0412702
12703 // Start the first transaction to set up the SpdySession
12704 HttpRequestInfo request1;
12705 request1.method = "GET";
12706 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0412707 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012708 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0412709 TestCompletionCallback callback1;
12710 EXPECT_EQ(ERR_IO_PENDING,
12711 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3412712 base::MessageLoop::current()->RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0412713
12714 EXPECT_EQ(OK, callback1.WaitForResult());
12715 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
12716
12717 // Now, start the HTTP request
12718 HttpRequestInfo request2;
12719 request2.method = "GET";
12720 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0412721 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012722 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0412723 TestCompletionCallback callback2;
12724 EXPECT_EQ(ERR_IO_PENDING,
12725 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3412726 base::MessageLoop::current()->RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0412727
12728 EXPECT_EQ(OK, callback2.WaitForResult());
12729 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
12730}
12731
bnc1b0e36852015-04-28 15:32:5912732class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
12733 public:
12734 void Run(bool pooling, bool valid) {
12735 HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org",
12736 443);
12737 HostPortPair alternative("www.example.org", 443);
12738
12739 base::FilePath certs_dir = GetTestCertsDirectory();
12740 scoped_refptr<X509Certificate> cert(
12741 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
12742 ASSERT_TRUE(cert.get());
12743 bool common_name_fallback_used;
12744 EXPECT_EQ(valid,
12745 cert->VerifyNameMatch(origin.host(), &common_name_fallback_used));
12746 EXPECT_TRUE(
12747 cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used));
12748 SSLSocketDataProvider ssl(ASYNC, OK);
12749 ssl.SetNextProto(GetParam());
12750 ssl.cert = cert;
12751 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12752
12753 // If pooling, then start a request to alternative first to create a
12754 // SpdySession.
12755 std::string url0 = "https://www.example.org:443";
12756 // Second request to origin, which has an alternative service, and could
12757 // open a connection to the alternative host or pool to the existing one.
12758 std::string url1("https://");
12759 url1.append(origin.host());
12760 url1.append(":443");
12761
12762 scoped_ptr<SpdyFrame> req0;
12763 scoped_ptr<SpdyFrame> req1;
12764 scoped_ptr<SpdyFrame> resp0;
12765 scoped_ptr<SpdyFrame> body0;
12766 scoped_ptr<SpdyFrame> resp1;
12767 scoped_ptr<SpdyFrame> body1;
12768 std::vector<MockWrite> writes;
12769 std::vector<MockRead> reads;
12770
12771 if (pooling) {
12772 req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), false, 1, LOWEST));
12773 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 3, LOWEST));
12774
12775 writes.push_back(CreateMockWrite(*req0, 0));
12776 writes.push_back(CreateMockWrite(*req1, 3));
12777
12778 resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12779 body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
12780 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12781 body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true));
12782
12783 reads.push_back(CreateMockRead(*resp0, 1));
12784 reads.push_back(CreateMockRead(*body0, 2));
12785 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4));
12786 reads.push_back(CreateMockRead(*resp1, 5));
12787 reads.push_back(CreateMockRead(*body1, 6));
12788 reads.push_back(MockRead(ASYNC, OK, 7));
12789 } else {
12790 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 1, LOWEST));
12791
12792 writes.push_back(CreateMockWrite(*req1, 0));
12793
12794 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12795 body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
12796
12797 reads.push_back(CreateMockRead(*resp1, 1));
12798 reads.push_back(CreateMockRead(*body1, 2));
12799 reads.push_back(MockRead(ASYNC, OK, 3));
12800 }
12801
rch32320842015-05-16 15:57:0912802 SequencedSocketData data(vector_as_array(&reads), reads.size(),
12803 vector_as_array(&writes), writes.size());
bnc1b0e36852015-04-28 15:32:5912804 session_deps_.socket_factory->AddSocketDataProvider(&data);
12805
12806 // Connection to the origin fails.
12807 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12808 StaticSocketDataProvider data_refused;
12809 data_refused.set_connect_data(mock_connect);
12810 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12811
bnc55ff9da2015-08-19 18:42:3512812 session_deps_.use_alternative_services = true;
mmenke6b3af6e2015-09-12 02:06:0612813 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc1b0e36852015-04-28 15:32:5912814 base::WeakPtr<HttpServerProperties> http_server_properties =
12815 session->http_server_properties();
12816 AlternativeService alternative_service(
12817 AlternateProtocolFromNextProto(GetParam()), alternative);
bnc7dc7e1b42015-07-28 14:43:1212818 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc1b0e36852015-04-28 15:32:5912819 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1212820 1.0, expiration);
bnc1b0e36852015-04-28 15:32:5912821
12822 // First request to alternative.
12823 if (pooling) {
12824 scoped_ptr<HttpTransaction> trans0(
12825 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12826 HttpRequestInfo request0;
12827 request0.method = "GET";
12828 request0.url = GURL(url0);
12829 request0.load_flags = 0;
12830 TestCompletionCallback callback0;
12831
12832 int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog());
12833 EXPECT_EQ(ERR_IO_PENDING, rv);
12834 rv = callback0.WaitForResult();
12835 EXPECT_EQ(OK, rv);
12836 }
12837
12838 // Second request to origin.
12839 scoped_ptr<HttpTransaction> trans1(
12840 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12841 HttpRequestInfo request1;
12842 request1.method = "GET";
12843 request1.url = GURL(url1);
12844 request1.load_flags = 0;
12845 TestCompletionCallback callback1;
12846
12847 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
12848 EXPECT_EQ(ERR_IO_PENDING, rv);
rch32320842015-05-16 15:57:0912849 base::MessageLoop::current()->RunUntilIdle();
12850 if (data.IsReadPaused()) {
12851 data.CompleteRead();
12852 }
bnc1b0e36852015-04-28 15:32:5912853 rv = callback1.WaitForResult();
12854 if (valid) {
12855 EXPECT_EQ(OK, rv);
12856 } else {
12857 if (pooling) {
12858 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
12859 } else {
12860 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv);
12861 }
12862 }
12863 }
12864};
12865
12866INSTANTIATE_TEST_CASE_P(NextProto,
12867 AltSvcCertificateVerificationTest,
12868 testing::Values(kProtoSPDY31,
bnc06d22432015-06-29 12:39:4312869 kProtoHTTP2));
bnc1b0e36852015-04-28 15:32:5912870
12871// The alternative service host must exhibit a certificate that is valid for the
12872// origin host. Test that this is enforced when pooling to an existing
12873// connection.
12874TEST_P(AltSvcCertificateVerificationTest, PoolingValid) {
12875 Run(true, true);
12876}
12877
12878TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) {
12879 Run(true, false);
12880}
12881
12882// The alternative service host must exhibit a certificate that is valid for the
12883// origin host. Test that this is enforced when opening a new connection.
12884TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) {
12885 Run(false, true);
12886}
12887
12888TEST_P(AltSvcCertificateVerificationTest, NewConnectionInvalid) {
12889 Run(false, false);
12890}
12891
bnc5452e2a2015-05-08 16:27:4212892// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
12893// with the alternative server. That connection should not be used.
12894TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
12895 HostPortPair origin("origin.example.org", 443);
12896 HostPortPair alternative("alternative.example.org", 443);
12897
12898 // Negotiate HTTP/1.1 with alternative.example.org.
12899 SSLSocketDataProvider ssl(ASYNC, OK);
12900 ssl.SetNextProto(kProtoHTTP11);
12901 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12902
12903 // No data should be read from the alternative, because HTTP/1.1 is
12904 // negotiated.
12905 StaticSocketDataProvider data;
12906 session_deps_.socket_factory->AddSocketDataProvider(&data);
12907
12908 // This test documents that an alternate Job should not be used if HTTP/1.1 is
12909 // negotiated. In order to test this, a failed connection to the origin is
12910 // mocked. This way the request relies on the alternate Job.
12911 StaticSocketDataProvider data_refused;
12912 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12913 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12914
12915 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3512916 session_deps_.use_alternative_services = true;
mmenke6b3af6e2015-09-12 02:06:0612917 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc5452e2a2015-05-08 16:27:4212918 base::WeakPtr<HttpServerProperties> http_server_properties =
12919 session->http_server_properties();
12920 AlternativeService alternative_service(
12921 AlternateProtocolFromNextProto(GetParam()), alternative);
bnc7dc7e1b42015-07-28 14:43:1212922 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc5452e2a2015-05-08 16:27:4212923 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1212924 1.0, expiration);
bnc5452e2a2015-05-08 16:27:4212925
12926 scoped_ptr<HttpTransaction> trans(
12927 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12928 HttpRequestInfo request;
12929 request.method = "GET";
12930 request.url = GURL("https://origin.example.org:443");
12931 request.load_flags = 0;
12932 TestCompletionCallback callback;
12933
12934 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
12935 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
12936 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12937 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED, callback.GetResult(rv));
12938}
12939
bnc40448a532015-05-11 19:13:1412940// A request to a server with an alternative service fires two Jobs: one to the
12941// origin, and an alternate one to the alternative server. If the former
12942// succeeds, the request should succeed, even if the latter fails because
12943// HTTP/1.1 is negotiated which is insufficient for alternative service.
12944TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
12945 HostPortPair origin("origin.example.org", 443);
12946 HostPortPair alternative("alternative.example.org", 443);
12947
12948 // Negotiate HTTP/1.1 with alternative.
12949 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
12950 alternative_ssl.SetNextProto(kProtoHTTP11);
12951 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
12952
12953 // No data should be read from the alternative, because HTTP/1.1 is
12954 // negotiated.
12955 StaticSocketDataProvider data;
12956 session_deps_.socket_factory->AddSocketDataProvider(&data);
12957
12958 // Negotiate HTTP/1.1 with origin.
12959 SSLSocketDataProvider origin_ssl(ASYNC, OK);
12960 origin_ssl.SetNextProto(kProtoHTTP11);
12961 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
12962
12963 MockWrite http_writes[] = {
12964 MockWrite(
12965 "GET / HTTP/1.1\r\n"
12966 "Host: origin.example.org\r\n"
12967 "Connection: keep-alive\r\n\r\n"),
12968 MockWrite(
12969 "GET /second HTTP/1.1\r\n"
12970 "Host: origin.example.org\r\n"
12971 "Connection: keep-alive\r\n\r\n"),
12972 };
12973
12974 MockRead http_reads[] = {
12975 MockRead("HTTP/1.1 200 OK\r\n"),
12976 MockRead("Content-Type: text/html\r\n"),
12977 MockRead("Content-Length: 6\r\n\r\n"),
12978 MockRead("foobar"),
12979 MockRead("HTTP/1.1 200 OK\r\n"),
12980 MockRead("Content-Type: text/html\r\n"),
12981 MockRead("Content-Length: 7\r\n\r\n"),
12982 MockRead("another"),
12983 };
12984 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12985 http_writes, arraysize(http_writes));
12986 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12987
12988 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3512989 session_deps_.use_alternative_services = true;
mmenke6b3af6e2015-09-12 02:06:0612990 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc40448a532015-05-11 19:13:1412991 base::WeakPtr<HttpServerProperties> http_server_properties =
12992 session->http_server_properties();
12993 AlternativeService alternative_service(
12994 AlternateProtocolFromNextProto(GetParam()), alternative);
bnc7dc7e1b42015-07-28 14:43:1212995 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc40448a532015-05-11 19:13:1412996 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1212997 1.0, expiration);
bnc40448a532015-05-11 19:13:1412998
12999 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
13000 HttpRequestInfo request1;
13001 request1.method = "GET";
13002 request1.url = GURL("https://origin.example.org:443");
13003 request1.load_flags = 0;
13004 TestCompletionCallback callback1;
13005
13006 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
13007 rv = callback1.GetResult(rv);
13008 EXPECT_EQ(OK, rv);
13009
13010 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
13011 ASSERT_TRUE(response1 != nullptr);
13012 ASSERT_TRUE(response1->headers.get() != nullptr);
13013 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13014
13015 std::string response_data1;
13016 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data1));
13017 EXPECT_EQ("foobar", response_data1);
13018
13019 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
13020 // for alternative service.
13021 EXPECT_TRUE(
13022 http_server_properties->IsAlternativeServiceBroken(alternative_service));
13023
13024 // Since |alternative_service| is broken, a second transaction to origin
13025 // should not start an alternate Job. It should pool to existing connection
13026 // to origin.
13027 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
13028 HttpRequestInfo request2;
13029 request2.method = "GET";
13030 request2.url = GURL("https://origin.example.org:443/second");
13031 request2.load_flags = 0;
13032 TestCompletionCallback callback2;
13033
13034 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
13035 rv = callback2.GetResult(rv);
13036 EXPECT_EQ(OK, rv);
13037
13038 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
13039 ASSERT_TRUE(response2 != nullptr);
13040 ASSERT_TRUE(response2->headers.get() != nullptr);
13041 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
13042
13043 std::string response_data2;
13044 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data2));
13045 EXPECT_EQ("another", response_data2);
13046}
13047
bnc5452e2a2015-05-08 16:27:4213048// Alternative service requires HTTP/2 (or SPDY), but there is already a
13049// HTTP/1.1 socket open to the alternative server. That socket should not be
13050// used.
13051TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
13052 HostPortPair origin("origin.example.org", 443);
13053 HostPortPair alternative("alternative.example.org", 443);
13054 std::string origin_url = "https://origin.example.org:443";
13055 std::string alternative_url = "https://alternative.example.org:443";
13056
13057 // Negotiate HTTP/1.1 with alternative.example.org.
13058 SSLSocketDataProvider ssl(ASYNC, OK);
13059 ssl.SetNextProto(kProtoHTTP11);
13060 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13061
13062 // HTTP/1.1 data for |request1| and |request2|.
13063 MockWrite http_writes[] = {
13064 MockWrite(
13065 "GET / HTTP/1.1\r\n"
13066 "Host: alternative.example.org\r\n"
13067 "Connection: keep-alive\r\n\r\n"),
13068 MockWrite(
13069 "GET / HTTP/1.1\r\n"
13070 "Host: alternative.example.org\r\n"
13071 "Connection: keep-alive\r\n\r\n"),
13072 };
13073
13074 MockRead http_reads[] = {
13075 MockRead(
13076 "HTTP/1.1 200 OK\r\n"
13077 "Content-Type: text/html; charset=iso-8859-1\r\n"
13078 "Content-Length: 40\r\n\r\n"
13079 "first HTTP/1.1 response from alternative"),
13080 MockRead(
13081 "HTTP/1.1 200 OK\r\n"
13082 "Content-Type: text/html; charset=iso-8859-1\r\n"
13083 "Content-Length: 41\r\n\r\n"
13084 "second HTTP/1.1 response from alternative"),
13085 };
13086 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13087 http_writes, arraysize(http_writes));
13088 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13089
13090 // This test documents that an alternate Job should not pool to an already
13091 // existing HTTP/1.1 connection. In order to test this, a failed connection
13092 // to the origin is mocked. This way |request2| relies on the alternate Job.
13093 StaticSocketDataProvider data_refused;
13094 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13095 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13096
13097 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3513098 session_deps_.use_alternative_services = true;
mmenke6b3af6e2015-09-12 02:06:0613099 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc5452e2a2015-05-08 16:27:4213100 base::WeakPtr<HttpServerProperties> http_server_properties =
13101 session->http_server_properties();
13102 AlternativeService alternative_service(
13103 AlternateProtocolFromNextProto(GetParam()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213104 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc5452e2a2015-05-08 16:27:4213105 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213106 1.0, expiration);
bnc5452e2a2015-05-08 16:27:4213107
13108 // First transaction to alternative to open an HTTP/1.1 socket.
13109 scoped_ptr<HttpTransaction> trans1(
13110 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13111 HttpRequestInfo request1;
13112 request1.method = "GET";
13113 request1.url = GURL(alternative_url);
13114 request1.load_flags = 0;
13115 TestCompletionCallback callback1;
13116
13117 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
13118 EXPECT_EQ(OK, callback1.GetResult(rv));
13119 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
13120 ASSERT_TRUE(response1);
13121 ASSERT_TRUE(response1->headers.get());
13122 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13123 EXPECT_TRUE(response1->was_npn_negotiated);
13124 EXPECT_FALSE(response1->was_fetched_via_spdy);
13125 std::string response_data1;
13126 ASSERT_EQ(OK, ReadTransaction(trans1.get(), &response_data1));
13127 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
13128
13129 // Request for origin.example.org, which has an alternative service. This
13130 // will start two Jobs: the alternative looks for connections to pool to,
13131 // finds one which is HTTP/1.1, and should ignore it, and should not try to
13132 // open other connections to alternative server. The Job to origin fails, so
13133 // this request fails.
13134 scoped_ptr<HttpTransaction> trans2(
13135 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13136 HttpRequestInfo request2;
13137 request2.method = "GET";
13138 request2.url = GURL(origin_url);
13139 request2.load_flags = 0;
13140 TestCompletionCallback callback2;
13141
13142 rv = trans2->Start(&request2, callback2.callback(), BoundNetLog());
13143 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback2.GetResult(rv));
13144
13145 // Another transaction to alternative. This is to test that the HTTP/1.1
13146 // socket is still open and in the pool.
13147 scoped_ptr<HttpTransaction> trans3(
13148 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13149 HttpRequestInfo request3;
13150 request3.method = "GET";
13151 request3.url = GURL(alternative_url);
13152 request3.load_flags = 0;
13153 TestCompletionCallback callback3;
13154
13155 rv = trans3->Start(&request3, callback3.callback(), BoundNetLog());
13156 EXPECT_EQ(OK, callback3.GetResult(rv));
13157 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
13158 ASSERT_TRUE(response3);
13159 ASSERT_TRUE(response3->headers.get());
13160 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
13161 EXPECT_TRUE(response3->was_npn_negotiated);
13162 EXPECT_FALSE(response3->was_fetched_via_spdy);
13163 std::string response_data3;
13164 ASSERT_EQ(OK, ReadTransaction(trans3.get(), &response_data3));
13165 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
13166}
13167
[email protected]23e482282013-06-14 16:08:0213168TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2313169 const std::string https_url = "https://www.example.org:8080/";
13170 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0413171
13172 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2313173 const HostPortPair host_port_pair("www.example.org", 8080);
lgarrona91df87f2014-12-05 00:51:3413174 scoped_ptr<SpdyFrame> connect(
13175 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
[email protected]cdf8f7e72013-05-23 10:56:4613176 scoped_ptr<SpdyFrame> req1(
13177 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
[email protected]23e482282013-06-14 16:08:0213178 scoped_ptr<SpdyFrame> wrapped_req1(
13179 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3913180
13181 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
[email protected]745aa9c2014-06-27 02:21:2913182 SpdyHeaderBlock req2_block;
bnc7ecc1122015-09-28 13:22:4913183 spdy_util_.MaybeAddVersionHeader(&req2_block);
[email protected]745aa9c2014-06-27 02:21:2913184 req2_block[spdy_util_.GetMethodKey()] = "GET";
bncce36dca22015-04-21 22:11:2313185 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
[email protected]745aa9c2014-06-27 02:21:2913186 req2_block[spdy_util_.GetSchemeKey()] = "http";
bnc7ecc1122015-09-28 13:22:4913187 req2_block[spdy_util_.GetPathKey()] = "/";
[email protected]601e03f12014-04-06 16:26:3913188 scoped_ptr<SpdyFrame> req2(
[email protected]745aa9c2014-06-27 02:21:2913189 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
[email protected]8450d722012-07-02 19:14:0413190
13191 MockWrite writes1[] = {
13192 CreateMockWrite(*connect, 0),
13193 CreateMockWrite(*wrapped_req1, 2),
13194 CreateMockWrite(*req2, 5),
13195 };
13196
[email protected]23e482282013-06-14 16:08:0213197 scoped_ptr<SpdyFrame> conn_resp(
13198 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13199 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13200 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
13201 scoped_ptr<SpdyFrame> wrapped_resp1(
13202 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
13203 scoped_ptr<SpdyFrame> wrapped_body1(
13204 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
13205 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13206 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]8450d722012-07-02 19:14:0413207 MockRead reads1[] = {
13208 CreateMockRead(*conn_resp, 1),
13209 CreateMockRead(*wrapped_resp1, 3),
13210 CreateMockRead(*wrapped_body1, 4),
13211 CreateMockRead(*resp2, 6),
13212 CreateMockRead(*body2, 7),
13213 MockRead(ASYNC, ERR_IO_PENDING, 8)
13214 };
13215
[email protected]dd54bd82012-07-19 23:44:5713216 DeterministicSocketData data1(reads1, arraysize(reads1),
13217 writes1, arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0413218 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5713219 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0413220
rdsmith82957ad2015-09-16 19:42:0313221 session_deps_.proxy_service =
13222 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:5113223 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0713224 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0413225 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
[email protected]23e482282013-06-14 16:08:0213226 ssl1.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:0713227 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0413228 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
[email protected]23e482282013-06-14 16:08:0213229 ssl2.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:0713230 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
13231 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0413232
mmenke6b3af6e2015-09-12 02:06:0613233 scoped_refptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:0713234 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
[email protected]8450d722012-07-02 19:14:0413235
13236 // Start the first transaction to set up the SpdySession
13237 HttpRequestInfo request1;
13238 request1.method = "GET";
13239 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0413240 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013241 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0413242 TestCompletionCallback callback1;
13243 EXPECT_EQ(ERR_IO_PENDING,
13244 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413245 base::MessageLoop::current()->RunUntilIdle();
[email protected]dd54bd82012-07-19 23:44:5713246 data1.RunFor(4);
[email protected]8450d722012-07-02 19:14:0413247
13248 EXPECT_EQ(OK, callback1.WaitForResult());
13249 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13250
[email protected]f6c63db52013-02-02 00:35:2213251 LoadTimingInfo load_timing_info1;
13252 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
13253 TestLoadTimingNotReusedWithPac(load_timing_info1,
13254 CONNECT_TIMING_HAS_SSL_TIMES);
13255
[email protected]8450d722012-07-02 19:14:0413256 // Now, start the HTTP request
13257 HttpRequestInfo request2;
13258 request2.method = "GET";
13259 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0413260 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013261 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0413262 TestCompletionCallback callback2;
13263 EXPECT_EQ(ERR_IO_PENDING,
13264 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413265 base::MessageLoop::current()->RunUntilIdle();
[email protected]dd54bd82012-07-19 23:44:5713266 data1.RunFor(3);
[email protected]8450d722012-07-02 19:14:0413267
13268 EXPECT_EQ(OK, callback2.WaitForResult());
13269 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2213270
13271 LoadTimingInfo load_timing_info2;
13272 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
13273 // The established SPDY sessions is considered reused by the HTTP request.
13274 TestLoadTimingReusedWithPac(load_timing_info2);
13275 // HTTP requests over a SPDY session should have a different connection
13276 // socket_log_id than requests over a tunnel.
13277 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0413278}
13279
[email protected]2d88e7d2012-07-19 17:55:1713280// Test that in the case where we have a SPDY session to a SPDY proxy
13281// that we do not pool other origins that resolve to the same IP when
13282// the certificate does not match the new origin.
13283// http://crbug.com/134690
[email protected]23e482282013-06-14 16:08:0213284TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2313285 const std::string url1 = "http://www.example.org/";
13286 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1713287 const std::string ip_addr = "1.2.3.4";
13288
13289 // SPDY GET for HTTP URL (through SPDY proxy)
[email protected]23e482282013-06-14 16:08:0213290 scoped_ptr<SpdyHeaderBlock> headers(
bncce36dca22015-04-21 22:11:2313291 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
[email protected]745aa9c2014-06-27 02:21:2913292 scoped_ptr<SpdyFrame> req1(
13293 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]2d88e7d2012-07-19 17:55:1713294
13295 MockWrite writes1[] = {
13296 CreateMockWrite(*req1, 0),
13297 };
13298
[email protected]23e482282013-06-14 16:08:0213299 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13300 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1713301 MockRead reads1[] = {
bncb9e20fc62015-08-17 17:19:3713302 CreateMockRead(*resp1, 1),
13303 CreateMockRead(*body1, 2),
13304 MockRead(ASYNC, OK, 3) // EOF
[email protected]2d88e7d2012-07-19 17:55:1713305 };
13306
13307 scoped_ptr<DeterministicSocketData> data1(
13308 new DeterministicSocketData(reads1, arraysize(reads1),
13309 writes1, arraysize(writes1)));
13310 IPAddressNumber ip;
13311 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
13312 IPEndPoint peer_addr = IPEndPoint(ip, 443);
13313 MockConnect connect_data1(ASYNC, OK, peer_addr);
13314 data1->set_connect_data(connect_data1);
13315
13316 // SPDY GET for HTTPS URL (direct)
[email protected]cdf8f7e72013-05-23 10:56:4613317 scoped_ptr<SpdyFrame> req2(
13318 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1713319
13320 MockWrite writes2[] = {
13321 CreateMockWrite(*req2, 0),
13322 };
13323
[email protected]23e482282013-06-14 16:08:0213324 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13325 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1713326 MockRead reads2[] = {
bncb9e20fc62015-08-17 17:19:3713327 CreateMockRead(*resp2, 1),
13328 CreateMockRead(*body2, 2),
13329 MockRead(ASYNC, OK, 3) // EOF
[email protected]2d88e7d2012-07-19 17:55:1713330 };
13331
13332 scoped_ptr<DeterministicSocketData> data2(
13333 new DeterministicSocketData(reads2, arraysize(reads2),
13334 writes2, arraysize(writes2)));
13335 MockConnect connect_data2(ASYNC, OK);
13336 data2->set_connect_data(connect_data2);
13337
13338 // Set up a proxy config that sends HTTP requests to a proxy, and
13339 // all others direct.
13340 ProxyConfig proxy_config;
13341 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
[email protected]bb88e1d32013-05-03 23:11:0713342 session_deps_.proxy_service.reset(new ProxyService(
csharrisonb7e3a082015-09-22 19:13:0413343 make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)), nullptr,
13344 NULL));
[email protected]2d88e7d2012-07-19 17:55:1713345
bncce36dca22015-04-21 22:11:2313346 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
13347 ssl1.SetNextProto(GetParam());
[email protected]2d88e7d2012-07-19 17:55:1713348 // Load a valid cert. Note, that this does not need to
13349 // be valid for proxy because the MockSSLClientSocket does
13350 // not actually verify it. But SpdySession will use this
13351 // to see if it is valid for the new origin
bncce36dca22015-04-21 22:11:2313352 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
13353 ASSERT_TRUE(ssl1.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0713354 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
13355 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
13356 data1.get());
[email protected]2d88e7d2012-07-19 17:55:1713357
13358 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
[email protected]23e482282013-06-14 16:08:0213359 ssl2.SetNextProto(GetParam());
[email protected]bb88e1d32013-05-03 23:11:0713360 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
13361 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
13362 data2.get());
[email protected]2d88e7d2012-07-19 17:55:1713363
[email protected]bb88e1d32013-05-03 23:11:0713364 session_deps_.host_resolver.reset(new MockCachingHostResolver());
bncce36dca22015-04-21 22:11:2313365 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0713366 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1713367
mmenke6b3af6e2015-09-12 02:06:0613368 scoped_refptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:0713369 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
[email protected]2d88e7d2012-07-19 17:55:1713370
13371 // Start the first transaction to set up the SpdySession
13372 HttpRequestInfo request1;
13373 request1.method = "GET";
13374 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1713375 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013376 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713377 TestCompletionCallback callback1;
13378 ASSERT_EQ(ERR_IO_PENDING,
13379 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
13380 data1->RunFor(3);
13381
13382 ASSERT_TRUE(callback1.have_result());
13383 EXPECT_EQ(OK, callback1.WaitForResult());
13384 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13385
13386 // Now, start the HTTP request
13387 HttpRequestInfo request2;
13388 request2.method = "GET";
13389 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1713390 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013391 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713392 TestCompletionCallback callback2;
13393 EXPECT_EQ(ERR_IO_PENDING,
13394 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413395 base::MessageLoop::current()->RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1713396 data2->RunFor(3);
13397
13398 ASSERT_TRUE(callback2.have_result());
13399 EXPECT_EQ(OK, callback2.WaitForResult());
13400 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13401}
13402
[email protected]85f97342013-04-17 06:12:2413403// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
13404// error) in SPDY session, removes the socket from pool and closes the SPDY
13405// session. Verify that new url's from the same HttpNetworkSession (and a new
13406// SpdySession) do work. http://crbug.com/224701
[email protected]23e482282013-06-14 16:08:0213407TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2313408 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2413409
13410 MockRead reads1[] = {
13411 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
13412 };
13413
mmenke11eb5152015-06-09 14:50:5013414 SequencedSocketData data1(reads1, arraysize(reads1), NULL, 0);
[email protected]85f97342013-04-17 06:12:2413415
[email protected]cdf8f7e72013-05-23 10:56:4613416 scoped_ptr<SpdyFrame> req2(
13417 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2413418 MockWrite writes2[] = {
13419 CreateMockWrite(*req2, 0),
13420 };
13421
[email protected]23e482282013-06-14 16:08:0213422 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13423 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]85f97342013-04-17 06:12:2413424 MockRead reads2[] = {
13425 CreateMockRead(*resp2, 1),
13426 CreateMockRead(*body2, 2),
13427 MockRead(ASYNC, OK, 3) // EOF
13428 };
13429
mmenke11eb5152015-06-09 14:50:5013430 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13431 arraysize(writes2));
[email protected]85f97342013-04-17 06:12:2413432
[email protected]85f97342013-04-17 06:12:2413433 SSLSocketDataProvider ssl1(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0213434 ssl1.SetNextProto(GetParam());
mmenke11eb5152015-06-09 14:50:5013435 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13436 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2413437
13438 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0213439 ssl2.SetNextProto(GetParam());
mmenke11eb5152015-06-09 14:50:5013440 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13441 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2413442
mmenke6b3af6e2015-09-12 02:06:0613443 scoped_refptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5013444 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2413445
13446 // Start the first transaction to set up the SpdySession and verify that
13447 // connection was closed.
13448 HttpRequestInfo request1;
13449 request1.method = "GET";
13450 request1.url = GURL(https_url);
13451 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013452 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2413453 TestCompletionCallback callback1;
13454 EXPECT_EQ(ERR_IO_PENDING,
13455 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]85f97342013-04-17 06:12:2413456 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
13457
13458 // Now, start the second request and make sure it succeeds.
13459 HttpRequestInfo request2;
13460 request2.method = "GET";
13461 request2.url = GURL(https_url);
13462 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013463 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2413464 TestCompletionCallback callback2;
13465 EXPECT_EQ(ERR_IO_PENDING,
13466 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]85f97342013-04-17 06:12:2413467
mmenke11eb5152015-06-09 14:50:5013468 ASSERT_EQ(OK, callback2.WaitForResult());
[email protected]85f97342013-04-17 06:12:2413469 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13470}
13471
[email protected]23e482282013-06-14 16:08:0213472TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]d7599122014-05-24 03:37:2313473 session_deps_.next_protos = SpdyNextProtos();
[email protected]483fa202013-05-14 01:07:0313474 ClientSocketPoolManager::set_max_sockets_per_group(
13475 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13476 ClientSocketPoolManager::set_max_sockets_per_pool(
13477 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13478
13479 // Use two different hosts with different IPs so they don't get pooled.
13480 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
13481 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
mmenke6b3af6e2015-09-12 02:06:0613482 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0313483
13484 SSLSocketDataProvider ssl1(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0213485 ssl1.SetNextProto(GetParam());
[email protected]483fa202013-05-14 01:07:0313486 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]23e482282013-06-14 16:08:0213487 ssl2.SetNextProto(GetParam());
[email protected]483fa202013-05-14 01:07:0313488 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13489 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13490
[email protected]cdf8f7e72013-05-23 10:56:4613491 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
[email protected]483fa202013-05-14 01:07:0313492 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
13493 MockWrite spdy1_writes[] = {
rch8e6c6c42015-05-01 14:05:1313494 CreateMockWrite(*host1_req, 0),
[email protected]483fa202013-05-14 01:07:0313495 };
[email protected]23e482282013-06-14 16:08:0213496 scoped_ptr<SpdyFrame> host1_resp(
13497 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13498 scoped_ptr<SpdyFrame> host1_resp_body(
13499 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]483fa202013-05-14 01:07:0313500 MockRead spdy1_reads[] = {
rch8e6c6c42015-05-01 14:05:1313501 CreateMockRead(*host1_resp, 1),
13502 CreateMockRead(*host1_resp_body, 2),
13503 MockRead(ASYNC, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0313504 };
13505
rch8e6c6c42015-05-01 14:05:1313506 scoped_ptr<SequencedSocketData> spdy1_data(
13507 new SequencedSocketData(spdy1_reads, arraysize(spdy1_reads), spdy1_writes,
13508 arraysize(spdy1_writes)));
[email protected]483fa202013-05-14 01:07:0313509 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
13510
[email protected]cdf8f7e72013-05-23 10:56:4613511 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
[email protected]483fa202013-05-14 01:07:0313512 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
13513 MockWrite spdy2_writes[] = {
rch8e6c6c42015-05-01 14:05:1313514 CreateMockWrite(*host2_req, 0),
[email protected]483fa202013-05-14 01:07:0313515 };
[email protected]23e482282013-06-14 16:08:0213516 scoped_ptr<SpdyFrame> host2_resp(
13517 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13518 scoped_ptr<SpdyFrame> host2_resp_body(
13519 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]483fa202013-05-14 01:07:0313520 MockRead spdy2_reads[] = {
rch8e6c6c42015-05-01 14:05:1313521 CreateMockRead(*host2_resp, 1),
13522 CreateMockRead(*host2_resp_body, 2),
13523 MockRead(ASYNC, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0313524 };
13525
rch8e6c6c42015-05-01 14:05:1313526 scoped_ptr<SequencedSocketData> spdy2_data(
13527 new SequencedSocketData(spdy2_reads, arraysize(spdy2_reads), spdy2_writes,
13528 arraysize(spdy2_writes)));
[email protected]483fa202013-05-14 01:07:0313529 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
13530
13531 MockWrite http_write[] = {
13532 MockWrite("GET / HTTP/1.1\r\n"
13533 "Host: www.a.com\r\n"
13534 "Connection: keep-alive\r\n\r\n"),
13535 };
13536
13537 MockRead http_read[] = {
13538 MockRead("HTTP/1.1 200 OK\r\n"),
13539 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
13540 MockRead("Content-Length: 6\r\n\r\n"),
13541 MockRead("hello!"),
13542 };
13543 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
13544 http_write, arraysize(http_write));
13545 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13546
13547 HostPortPair host_port_pair_a("www.a.com", 443);
[email protected]e6d017652013-05-17 18:01:4013548 SpdySessionKey spdy_session_key_a(
[email protected]314b03992014-04-01 01:28:5313549 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0313550 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613551 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313552
13553 TestCompletionCallback callback;
13554 HttpRequestInfo request1;
13555 request1.method = "GET";
13556 request1.url = GURL("https://www.a.com/");
13557 request1.load_flags = 0;
13558 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5013559 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0313560
13561 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
13562 EXPECT_EQ(ERR_IO_PENDING, rv);
13563 EXPECT_EQ(OK, callback.WaitForResult());
13564
13565 const HttpResponseInfo* response = trans->GetResponseInfo();
13566 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013567 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]483fa202013-05-14 01:07:0313568 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13569 EXPECT_TRUE(response->was_fetched_via_spdy);
13570 EXPECT_TRUE(response->was_npn_negotiated);
13571
13572 std::string response_data;
13573 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
13574 EXPECT_EQ("hello!", response_data);
13575 trans.reset();
13576 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2613577 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313578
13579 HostPortPair host_port_pair_b("www.b.com", 443);
[email protected]e6d017652013-05-17 18:01:4013580 SpdySessionKey spdy_session_key_b(
[email protected]314b03992014-04-01 01:28:5313581 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0313582 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613583 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0313584 HttpRequestInfo request2;
13585 request2.method = "GET";
13586 request2.url = GURL("https://www.b.com/");
13587 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013588 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0313589
13590 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
13591 EXPECT_EQ(ERR_IO_PENDING, rv);
13592 EXPECT_EQ(OK, callback.WaitForResult());
13593
13594 response = trans->GetResponseInfo();
13595 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013596 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]483fa202013-05-14 01:07:0313597 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13598 EXPECT_TRUE(response->was_fetched_via_spdy);
13599 EXPECT_TRUE(response->was_npn_negotiated);
13600 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
13601 EXPECT_EQ("hello!", response_data);
13602 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613603 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313604 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2613605 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0313606
13607 HostPortPair host_port_pair_a1("www.a.com", 80);
[email protected]e6d017652013-05-17 18:01:4013608 SpdySessionKey spdy_session_key_a1(
[email protected]314b03992014-04-01 01:28:5313609 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0313610 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613611 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0313612 HttpRequestInfo request3;
13613 request3.method = "GET";
13614 request3.url = GURL("http://www.a.com/");
13615 request3.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013616 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0313617
13618 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
13619 EXPECT_EQ(ERR_IO_PENDING, rv);
13620 EXPECT_EQ(OK, callback.WaitForResult());
13621
13622 response = trans->GetResponseInfo();
13623 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013624 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]483fa202013-05-14 01:07:0313625 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13626 EXPECT_FALSE(response->was_fetched_via_spdy);
13627 EXPECT_FALSE(response->was_npn_negotiated);
13628 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
13629 EXPECT_EQ("hello!", response_data);
13630 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613631 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313632 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613633 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0313634}
13635
[email protected]79e1fd62013-06-20 06:50:0413636TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
13637 HttpRequestInfo request;
13638 request.method = "GET";
bncce36dca22015-04-21 22:11:2313639 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413640 request.load_flags = 0;
13641
mmenke6b3af6e2015-09-12 02:06:0613642 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0413643 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113644 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413645
ttuttled9dbc652015-09-29 20:00:5913646 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0413647 StaticSocketDataProvider data;
13648 data.set_connect_data(mock_connect);
13649 session_deps_.socket_factory->AddSocketDataProvider(&data);
13650
13651 TestCompletionCallback callback;
13652
13653 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13654 EXPECT_EQ(ERR_IO_PENDING, rv);
13655
13656 rv = callback.WaitForResult();
ttuttled9dbc652015-09-29 20:00:5913657 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
[email protected]79e1fd62013-06-20 06:50:0413658
[email protected]79e1fd62013-06-20 06:50:0413659 // We don't care whether this succeeds or fails, but it shouldn't crash.
13660 HttpRequestHeaders request_headers;
13661 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4713662
13663 ConnectionAttempts attempts;
13664 trans->GetConnectionAttempts(&attempts);
13665 ASSERT_EQ(1u, attempts.size());
ttuttled9dbc652015-09-29 20:00:5913666 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
13667
13668 IPEndPoint endpoint;
13669 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
13670 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0413671}
13672
13673TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
13674 HttpRequestInfo request;
13675 request.method = "GET";
bncce36dca22015-04-21 22:11:2313676 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413677 request.load_flags = 0;
13678
mmenke6b3af6e2015-09-12 02:06:0613679 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0413680 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113681 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413682
ttuttled9dbc652015-09-29 20:00:5913683 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0413684 StaticSocketDataProvider data;
13685 data.set_connect_data(mock_connect);
13686 session_deps_.socket_factory->AddSocketDataProvider(&data);
13687
13688 TestCompletionCallback callback;
13689
13690 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13691 EXPECT_EQ(ERR_IO_PENDING, rv);
13692
13693 rv = callback.WaitForResult();
ttuttled9dbc652015-09-29 20:00:5913694 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
[email protected]79e1fd62013-06-20 06:50:0413695
[email protected]79e1fd62013-06-20 06:50:0413696 // We don't care whether this succeeds or fails, but it shouldn't crash.
13697 HttpRequestHeaders request_headers;
13698 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4713699
13700 ConnectionAttempts attempts;
13701 trans->GetConnectionAttempts(&attempts);
13702 ASSERT_EQ(1u, attempts.size());
ttuttled9dbc652015-09-29 20:00:5913703 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
13704
13705 IPEndPoint endpoint;
13706 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
13707 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0413708}
13709
13710TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
13711 HttpRequestInfo request;
13712 request.method = "GET";
bncce36dca22015-04-21 22:11:2313713 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413714 request.load_flags = 0;
13715
mmenke6b3af6e2015-09-12 02:06:0613716 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0413717 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113718 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413719
13720 MockWrite data_writes[] = {
13721 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13722 };
13723 MockRead data_reads[] = {
13724 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
13725 };
13726
13727 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13728 data_writes, arraysize(data_writes));
13729 session_deps_.socket_factory->AddSocketDataProvider(&data);
13730
13731 TestCompletionCallback callback;
13732
13733 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13734 EXPECT_EQ(ERR_IO_PENDING, rv);
13735
13736 rv = callback.WaitForResult();
13737 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13738
[email protected]79e1fd62013-06-20 06:50:0413739 HttpRequestHeaders request_headers;
13740 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13741 EXPECT_TRUE(request_headers.HasHeader("Host"));
13742}
13743
13744TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
13745 HttpRequestInfo request;
13746 request.method = "GET";
bncce36dca22015-04-21 22:11:2313747 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413748 request.load_flags = 0;
13749
mmenke6b3af6e2015-09-12 02:06:0613750 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0413751 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113752 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413753
13754 MockWrite data_writes[] = {
13755 MockWrite(ASYNC, ERR_CONNECTION_RESET),
13756 };
13757 MockRead data_reads[] = {
13758 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
13759 };
13760
13761 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13762 data_writes, arraysize(data_writes));
13763 session_deps_.socket_factory->AddSocketDataProvider(&data);
13764
13765 TestCompletionCallback callback;
13766
13767 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13768 EXPECT_EQ(ERR_IO_PENDING, rv);
13769
13770 rv = callback.WaitForResult();
13771 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13772
[email protected]79e1fd62013-06-20 06:50:0413773 HttpRequestHeaders request_headers;
13774 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13775 EXPECT_TRUE(request_headers.HasHeader("Host"));
13776}
13777
13778TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
13779 HttpRequestInfo request;
13780 request.method = "GET";
bncce36dca22015-04-21 22:11:2313781 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413782 request.load_flags = 0;
13783
mmenke6b3af6e2015-09-12 02:06:0613784 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0413785 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113786 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413787
13788 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2313789 MockWrite(
13790 "GET / HTTP/1.1\r\n"
13791 "Host: www.example.org\r\n"
13792 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0413793 };
13794 MockRead data_reads[] = {
13795 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
13796 };
13797
13798 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13799 data_writes, arraysize(data_writes));
13800 session_deps_.socket_factory->AddSocketDataProvider(&data);
13801
13802 TestCompletionCallback callback;
13803
13804 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13805 EXPECT_EQ(ERR_IO_PENDING, rv);
13806
13807 rv = callback.WaitForResult();
13808 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13809
[email protected]79e1fd62013-06-20 06:50:0413810 HttpRequestHeaders request_headers;
13811 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13812 EXPECT_TRUE(request_headers.HasHeader("Host"));
13813}
13814
13815TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
13816 HttpRequestInfo request;
13817 request.method = "GET";
bncce36dca22015-04-21 22:11:2313818 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413819 request.load_flags = 0;
13820
mmenke6b3af6e2015-09-12 02:06:0613821 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0413822 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113823 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413824
13825 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2313826 MockWrite(
13827 "GET / HTTP/1.1\r\n"
13828 "Host: www.example.org\r\n"
13829 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0413830 };
13831 MockRead data_reads[] = {
13832 MockRead(ASYNC, ERR_CONNECTION_RESET),
13833 };
13834
13835 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13836 data_writes, arraysize(data_writes));
13837 session_deps_.socket_factory->AddSocketDataProvider(&data);
13838
13839 TestCompletionCallback callback;
13840
13841 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13842 EXPECT_EQ(ERR_IO_PENDING, rv);
13843
13844 rv = callback.WaitForResult();
13845 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13846
[email protected]79e1fd62013-06-20 06:50:0413847 HttpRequestHeaders request_headers;
13848 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13849 EXPECT_TRUE(request_headers.HasHeader("Host"));
13850}
13851
13852TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
13853 HttpRequestInfo request;
13854 request.method = "GET";
bncce36dca22015-04-21 22:11:2313855 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413856 request.load_flags = 0;
13857 request.extra_headers.SetHeader("X-Foo", "bar");
13858
mmenke6b3af6e2015-09-12 02:06:0613859 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0413860 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113861 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413862
13863 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2313864 MockWrite(
13865 "GET / HTTP/1.1\r\n"
13866 "Host: www.example.org\r\n"
13867 "Connection: keep-alive\r\n"
13868 "X-Foo: bar\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0413869 };
13870 MockRead data_reads[] = {
13871 MockRead("HTTP/1.1 200 OK\r\n"
13872 "Content-Length: 5\r\n\r\n"
13873 "hello"),
13874 MockRead(ASYNC, ERR_UNEXPECTED),
13875 };
13876
13877 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
13878 data_writes, arraysize(data_writes));
13879 session_deps_.socket_factory->AddSocketDataProvider(&data);
13880
13881 TestCompletionCallback callback;
13882
13883 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13884 EXPECT_EQ(ERR_IO_PENDING, rv);
13885
13886 rv = callback.WaitForResult();
13887 EXPECT_EQ(OK, rv);
13888
13889 HttpRequestHeaders request_headers;
13890 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
13891 std::string foo;
13892 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
13893 EXPECT_EQ("bar", foo);
13894}
13895
[email protected]bf828982013-08-14 18:01:4713896namespace {
13897
yhiranoa7e05bb2014-11-06 05:40:3913898// Fake HttpStream that simply records calls to SetPriority().
13899class FakeStream : public HttpStream,
[email protected]e86839fd2013-08-14 18:29:0313900 public base::SupportsWeakPtr<FakeStream> {
13901 public:
13902 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
dchengb03027d2014-10-21 12:00:2013903 ~FakeStream() override {}
[email protected]e86839fd2013-08-14 18:29:0313904
13905 RequestPriority priority() const { return priority_; }
13906
dchengb03027d2014-10-21 12:00:2013907 int InitializeStream(const HttpRequestInfo* request_info,
13908 RequestPriority priority,
13909 const BoundNetLog& net_log,
13910 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0313911 return ERR_IO_PENDING;
13912 }
13913
dchengb03027d2014-10-21 12:00:2013914 int SendRequest(const HttpRequestHeaders& request_headers,
13915 HttpResponseInfo* response,
13916 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0313917 ADD_FAILURE();
13918 return ERR_UNEXPECTED;
13919 }
13920
dchengb03027d2014-10-21 12:00:2013921 int ReadResponseHeaders(const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0313922 ADD_FAILURE();
13923 return ERR_UNEXPECTED;
13924 }
13925
dchengb03027d2014-10-21 12:00:2013926 int ReadResponseBody(IOBuffer* buf,
13927 int buf_len,
13928 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0313929 ADD_FAILURE();
13930 return ERR_UNEXPECTED;
13931 }
13932
dchengb03027d2014-10-21 12:00:2013933 void Close(bool not_reusable) override {}
[email protected]e86839fd2013-08-14 18:29:0313934
dchengb03027d2014-10-21 12:00:2013935 bool IsResponseBodyComplete() const override {
[email protected]e86839fd2013-08-14 18:29:0313936 ADD_FAILURE();
13937 return false;
13938 }
13939
dchengb03027d2014-10-21 12:00:2013940 bool IsConnectionReused() const override {
[email protected]e86839fd2013-08-14 18:29:0313941 ADD_FAILURE();
13942 return false;
13943 }
13944
dchengb03027d2014-10-21 12:00:2013945 void SetConnectionReused() override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0313946
mmenkebd84c392015-09-02 14:12:3413947 bool CanReuseConnection() const override { return false; }
[email protected]e86839fd2013-08-14 18:29:0313948
sclittle4de1bab92015-09-22 21:28:2413949 int64_t GetTotalReceivedBytes() const override {
[email protected]bc92bc972013-12-13 08:32:5913950 ADD_FAILURE();
13951 return 0;
13952 }
13953
sclittlebe1ccf62015-09-02 19:40:3613954 int64_t GetTotalSentBytes() const override {
13955 ADD_FAILURE();
13956 return 0;
13957 }
13958
dchengb03027d2014-10-21 12:00:2013959 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
[email protected]e86839fd2013-08-14 18:29:0313960 ADD_FAILURE();
13961 return false;
13962 }
13963
dchengb03027d2014-10-21 12:00:2013964 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
13965
13966 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
[email protected]e86839fd2013-08-14 18:29:0313967 ADD_FAILURE();
13968 }
13969
ttuttled9dbc652015-09-29 20:00:5913970 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
13971
dchengb03027d2014-10-21 12:00:2013972 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0313973
dchengb03027d2014-10-21 12:00:2013974 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]e86839fd2013-08-14 18:29:0313975
yhiranoa7e05bb2014-11-06 05:40:3913976 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
13977
13978 HttpStream* RenewStreamForAuth() override { return NULL; }
13979
[email protected]e86839fd2013-08-14 18:29:0313980 private:
13981 RequestPriority priority_;
13982
13983 DISALLOW_COPY_AND_ASSIGN(FakeStream);
13984};
13985
13986// Fake HttpStreamRequest that simply records calls to SetPriority()
13987// and vends FakeStreams with its current priority.
[email protected]bf828982013-08-14 18:01:4713988class FakeStreamRequest : public HttpStreamRequest,
13989 public base::SupportsWeakPtr<FakeStreamRequest> {
13990 public:
[email protected]e86839fd2013-08-14 18:29:0313991 FakeStreamRequest(RequestPriority priority,
13992 HttpStreamRequest::Delegate* delegate)
13993 : priority_(priority),
[email protected]831e4a32013-11-14 02:14:4413994 delegate_(delegate),
13995 websocket_stream_create_helper_(NULL) {}
13996
13997 FakeStreamRequest(RequestPriority priority,
13998 HttpStreamRequest::Delegate* delegate,
13999 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
14000 : priority_(priority),
14001 delegate_(delegate),
14002 websocket_stream_create_helper_(create_helper) {}
[email protected]e86839fd2013-08-14 18:29:0314003
dchengb03027d2014-10-21 12:00:2014004 ~FakeStreamRequest() override {}
[email protected]bf828982013-08-14 18:01:4714005
14006 RequestPriority priority() const { return priority_; }
14007
[email protected]831e4a32013-11-14 02:14:4414008 const WebSocketHandshakeStreamBase::CreateHelper*
14009 websocket_stream_create_helper() const {
14010 return websocket_stream_create_helper_;
14011 }
14012
[email protected]e86839fd2013-08-14 18:29:0314013 // Create a new FakeStream and pass it to the request's
14014 // delegate. Returns a weak pointer to the FakeStream.
14015 base::WeakPtr<FakeStream> FinishStreamRequest() {
14016 FakeStream* fake_stream = new FakeStream(priority_);
14017 // Do this before calling OnStreamReady() as OnStreamReady() may
14018 // immediately delete |fake_stream|.
14019 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
14020 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
14021 return weak_stream;
14022 }
14023
dchengb03027d2014-10-21 12:00:2014024 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
[email protected]bf828982013-08-14 18:01:4714025 ADD_FAILURE();
14026 return ERR_UNEXPECTED;
14027 }
14028
dchengb03027d2014-10-21 12:00:2014029 LoadState GetLoadState() const override {
[email protected]bf828982013-08-14 18:01:4714030 ADD_FAILURE();
14031 return LoadState();
14032 }
14033
dchengb03027d2014-10-21 12:00:2014034 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]bf828982013-08-14 18:01:4714035
dchengb03027d2014-10-21 12:00:2014036 bool was_npn_negotiated() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714037
dchengb03027d2014-10-21 12:00:2014038 NextProto protocol_negotiated() const override { return kProtoUnknown; }
[email protected]bf828982013-08-14 18:01:4714039
dchengb03027d2014-10-21 12:00:2014040 bool using_spdy() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714041
ttuttle1f2d7e92015-04-28 16:17:4714042 const ConnectionAttempts& connection_attempts() const override {
14043 static ConnectionAttempts no_attempts;
14044 return no_attempts;
14045 }
14046
[email protected]bf828982013-08-14 18:01:4714047 private:
14048 RequestPriority priority_;
[email protected]e86839fd2013-08-14 18:29:0314049 HttpStreamRequest::Delegate* const delegate_;
[email protected]831e4a32013-11-14 02:14:4414050 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
[email protected]bf828982013-08-14 18:01:4714051
14052 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
14053};
14054
14055// Fake HttpStreamFactory that vends FakeStreamRequests.
14056class FakeStreamFactory : public HttpStreamFactory {
14057 public:
14058 FakeStreamFactory() {}
dchengb03027d2014-10-21 12:00:2014059 ~FakeStreamFactory() override {}
[email protected]bf828982013-08-14 18:01:4714060
14061 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
14062 // RequestStream() (which may be NULL if it was destroyed already).
14063 base::WeakPtr<FakeStreamRequest> last_stream_request() {
14064 return last_stream_request_;
14065 }
14066
dchengb03027d2014-10-21 12:00:2014067 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
14068 RequestPriority priority,
14069 const SSLConfig& server_ssl_config,
14070 const SSLConfig& proxy_ssl_config,
14071 HttpStreamRequest::Delegate* delegate,
14072 const BoundNetLog& net_log) override {
[email protected]e86839fd2013-08-14 18:29:0314073 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
[email protected]bf828982013-08-14 18:01:4714074 last_stream_request_ = fake_request->AsWeakPtr();
14075 return fake_request;
14076 }
14077
dchengb03027d2014-10-21 12:00:2014078 HttpStreamRequest* RequestWebSocketHandshakeStream(
[email protected]bf828982013-08-14 18:01:4714079 const HttpRequestInfo& info,
14080 RequestPriority priority,
14081 const SSLConfig& server_ssl_config,
14082 const SSLConfig& proxy_ssl_config,
14083 HttpStreamRequest::Delegate* delegate,
[email protected]467086b2013-11-12 08:19:4614084 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
mostynbba063d6032014-10-09 11:01:1314085 const BoundNetLog& net_log) override {
[email protected]831e4a32013-11-14 02:14:4414086 FakeStreamRequest* fake_request =
14087 new FakeStreamRequest(priority, delegate, create_helper);
14088 last_stream_request_ = fake_request->AsWeakPtr();
14089 return fake_request;
[email protected]bf828982013-08-14 18:01:4714090 }
14091
dchengb03027d2014-10-21 12:00:2014092 void PreconnectStreams(int num_streams,
14093 const HttpRequestInfo& info,
dchengb03027d2014-10-21 12:00:2014094 const SSLConfig& server_ssl_config,
14095 const SSLConfig& proxy_ssl_config) override {
[email protected]bf828982013-08-14 18:01:4714096 ADD_FAILURE();
14097 }
14098
dchengb03027d2014-10-21 12:00:2014099 const HostMappingRules* GetHostMappingRules() const override {
[email protected]bf828982013-08-14 18:01:4714100 ADD_FAILURE();
14101 return NULL;
14102 }
14103
14104 private:
14105 base::WeakPtr<FakeStreamRequest> last_stream_request_;
14106
14107 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
14108};
14109
Adam Rice425cf122015-01-19 06:18:2414110// TODO(ricea): Maybe unify this with the one in
14111// url_request_http_job_unittest.cc ?
14112class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
14113 public:
14114 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection,
14115 bool using_proxy)
14116 : state_(connection.release(), using_proxy) {}
14117
14118 // Fake implementation of HttpStreamBase methods.
14119 // This ends up being quite "real" because this object has to really send data
14120 // on the mock socket. It might be easier to use the real implementation, but
14121 // the fact that the WebSocket code is not compiled on iOS makes that
14122 // difficult.
14123 int InitializeStream(const HttpRequestInfo* request_info,
14124 RequestPriority priority,
14125 const BoundNetLog& net_log,
14126 const CompletionCallback& callback) override {
14127 state_.Initialize(request_info, priority, net_log, callback);
14128 return OK;
14129 }
14130
14131 int SendRequest(const HttpRequestHeaders& request_headers,
14132 HttpResponseInfo* response,
14133 const CompletionCallback& callback) override {
14134 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
14135 response, callback);
14136 }
14137
14138 int ReadResponseHeaders(const CompletionCallback& callback) override {
14139 return parser()->ReadResponseHeaders(callback);
14140 }
14141
14142 int ReadResponseBody(IOBuffer* buf,
14143 int buf_len,
14144 const CompletionCallback& callback) override {
14145 NOTREACHED();
14146 return ERR_IO_PENDING;
14147 }
14148
14149 void Close(bool not_reusable) override {
14150 if (parser())
14151 parser()->Close(true);
14152 }
14153
14154 bool IsResponseBodyComplete() const override {
14155 NOTREACHED();
14156 return false;
14157 }
14158
Adam Rice425cf122015-01-19 06:18:2414159 bool IsConnectionReused() const override {
14160 NOTREACHED();
14161 return false;
14162 }
14163 void SetConnectionReused() override { NOTREACHED(); }
14164
mmenkebd84c392015-09-02 14:12:3414165 bool CanReuseConnection() const override { return false; }
Adam Rice425cf122015-01-19 06:18:2414166
sclittle4de1bab92015-09-22 21:28:2414167 int64_t GetTotalReceivedBytes() const override {
Adam Rice425cf122015-01-19 06:18:2414168 NOTREACHED();
14169 return 0;
14170 }
14171
sclittlebe1ccf62015-09-02 19:40:3614172 int64_t GetTotalSentBytes() const override {
14173 NOTREACHED();
14174 return 0;
14175 }
14176
Adam Rice425cf122015-01-19 06:18:2414177 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
14178 NOTREACHED();
14179 return false;
14180 }
14181
Adam Ricecb76ac62015-02-20 05:33:2514182 void GetSSLInfo(SSLInfo* ssl_info) override {}
Adam Rice425cf122015-01-19 06:18:2414183
14184 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
14185 NOTREACHED();
14186 }
14187
ttuttled9dbc652015-09-29 20:00:5914188 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
14189
Adam Rice425cf122015-01-19 06:18:2414190 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
14191
14192 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
14193
14194 UploadProgress GetUploadProgress() const override {
14195 NOTREACHED();
14196 return UploadProgress();
14197 }
14198
14199 HttpStream* RenewStreamForAuth() override {
14200 NOTREACHED();
14201 return nullptr;
14202 }
14203
14204 // Fake implementation of WebSocketHandshakeStreamBase method(s)
14205 scoped_ptr<WebSocketStream> Upgrade() override {
14206 NOTREACHED();
14207 return scoped_ptr<WebSocketStream>();
14208 }
14209
14210 private:
14211 HttpStreamParser* parser() const { return state_.parser(); }
14212 HttpBasicState state_;
14213
14214 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
14215};
14216
[email protected]831e4a32013-11-14 02:14:4414217// TODO(yhirano): Split this class out into a net/websockets file, if it is
14218// worth doing.
14219class FakeWebSocketStreamCreateHelper :
14220 public WebSocketHandshakeStreamBase::CreateHelper {
14221 public:
dchengb03027d2014-10-21 12:00:2014222 WebSocketHandshakeStreamBase* CreateBasicStream(
[email protected]7e841a52013-11-22 09:04:2114223 scoped_ptr<ClientSocketHandle> connection,
mostynbba063d6032014-10-09 11:01:1314224 bool using_proxy) override {
Adam Rice425cf122015-01-19 06:18:2414225 return new FakeWebSocketBasicHandshakeStream(connection.Pass(),
14226 using_proxy);
[email protected]831e4a32013-11-14 02:14:4414227 }
14228
dchengb03027d2014-10-21 12:00:2014229 WebSocketHandshakeStreamBase* CreateSpdyStream(
[email protected]831e4a32013-11-14 02:14:4414230 const base::WeakPtr<SpdySession>& session,
mostynbba063d6032014-10-09 11:01:1314231 bool use_relative_url) override {
[email protected]831e4a32013-11-14 02:14:4414232 NOTREACHED();
14233 return NULL;
14234 };
14235
dchengb03027d2014-10-21 12:00:2014236 ~FakeWebSocketStreamCreateHelper() override {}
[email protected]831e4a32013-11-14 02:14:4414237
14238 virtual scoped_ptr<WebSocketStream> Upgrade() {
14239 NOTREACHED();
14240 return scoped_ptr<WebSocketStream>();
14241 }
14242};
14243
[email protected]bf828982013-08-14 18:01:4714244} // namespace
14245
14246// Make sure that HttpNetworkTransaction passes on its priority to its
14247// stream request on start.
14248TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
mmenke6b3af6e2015-09-12 02:06:0614249 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14250 HttpNetworkSessionPeer peer(session);
[email protected]bf828982013-08-14 18:01:4714251 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414252 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714253
dcheng48459ac22014-08-26 00:46:4114254 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714255
14256 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
14257
14258 HttpRequestInfo request;
14259 TestCompletionCallback callback;
14260 EXPECT_EQ(ERR_IO_PENDING,
14261 trans.Start(&request, callback.callback(), BoundNetLog()));
14262
14263 base::WeakPtr<FakeStreamRequest> fake_request =
14264 fake_factory->last_stream_request();
14265 ASSERT_TRUE(fake_request != NULL);
14266 EXPECT_EQ(LOW, fake_request->priority());
14267}
14268
14269// Make sure that HttpNetworkTransaction passes on its priority
14270// updates to its stream request.
14271TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
mmenke6b3af6e2015-09-12 02:06:0614272 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14273 HttpNetworkSessionPeer peer(session);
[email protected]bf828982013-08-14 18:01:4714274 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414275 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714276
dcheng48459ac22014-08-26 00:46:4114277 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714278
14279 HttpRequestInfo request;
14280 TestCompletionCallback callback;
14281 EXPECT_EQ(ERR_IO_PENDING,
14282 trans.Start(&request, callback.callback(), BoundNetLog()));
14283
14284 base::WeakPtr<FakeStreamRequest> fake_request =
14285 fake_factory->last_stream_request();
14286 ASSERT_TRUE(fake_request != NULL);
14287 EXPECT_EQ(LOW, fake_request->priority());
14288
14289 trans.SetPriority(LOWEST);
14290 ASSERT_TRUE(fake_request != NULL);
14291 EXPECT_EQ(LOWEST, fake_request->priority());
14292}
14293
[email protected]e86839fd2013-08-14 18:29:0314294// Make sure that HttpNetworkTransaction passes on its priority
14295// updates to its stream.
14296TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
mmenke6b3af6e2015-09-12 02:06:0614297 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14298 HttpNetworkSessionPeer peer(session);
[email protected]e86839fd2013-08-14 18:29:0314299 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414300 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]e86839fd2013-08-14 18:29:0314301
dcheng48459ac22014-08-26 00:46:4114302 HttpNetworkTransaction trans(LOW, session.get());
[email protected]e86839fd2013-08-14 18:29:0314303
14304 HttpRequestInfo request;
14305 TestCompletionCallback callback;
14306 EXPECT_EQ(ERR_IO_PENDING,
14307 trans.Start(&request, callback.callback(), BoundNetLog()));
14308
14309 base::WeakPtr<FakeStreamRequest> fake_request =
14310 fake_factory->last_stream_request();
14311 ASSERT_TRUE(fake_request != NULL);
14312 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
14313 ASSERT_TRUE(fake_stream != NULL);
14314 EXPECT_EQ(LOW, fake_stream->priority());
14315
14316 trans.SetPriority(LOWEST);
14317 EXPECT_EQ(LOWEST, fake_stream->priority());
14318}
14319
[email protected]831e4a32013-11-14 02:14:4414320TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
14321 // The same logic needs to be tested for both ws: and wss: schemes, but this
14322 // test is already parameterised on NextProto, so it uses a loop to verify
14323 // that the different schemes work.
bncce36dca22015-04-21 22:11:2314324 std::string test_cases[] = {"ws://www.example.org/",
14325 "wss://www.example.org/"};
[email protected]831e4a32013-11-14 02:14:4414326 for (size_t i = 0; i < arraysize(test_cases); ++i) {
mmenke6b3af6e2015-09-12 02:06:0614327 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14328 HttpNetworkSessionPeer peer(session);
[email protected]831e4a32013-11-14 02:14:4414329 FakeStreamFactory* fake_factory = new FakeStreamFactory();
14330 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
[email protected]0191b51c2013-11-18 10:55:2314331 peer.SetHttpStreamFactoryForWebSocket(
[email protected]831e4a32013-11-14 02:14:4414332 scoped_ptr<HttpStreamFactory>(fake_factory));
14333
dcheng48459ac22014-08-26 00:46:4114334 HttpNetworkTransaction trans(LOW, session.get());
[email protected]831e4a32013-11-14 02:14:4414335 trans.SetWebSocketHandshakeStreamCreateHelper(
14336 &websocket_stream_create_helper);
14337
14338 HttpRequestInfo request;
14339 TestCompletionCallback callback;
14340 request.method = "GET";
14341 request.url = GURL(test_cases[i]);
14342
14343 EXPECT_EQ(ERR_IO_PENDING,
14344 trans.Start(&request, callback.callback(), BoundNetLog()));
14345
14346 base::WeakPtr<FakeStreamRequest> fake_request =
14347 fake_factory->last_stream_request();
14348 ASSERT_TRUE(fake_request != NULL);
14349 EXPECT_EQ(&websocket_stream_create_helper,
14350 fake_request->websocket_stream_create_helper());
14351 }
14352}
14353
[email protected]043b68c82013-08-22 23:41:5214354// Tests that when a used socket is returned to the SSL socket pool, it's closed
14355// if the transport socket pool is stalled on the global socket limit.
14356TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
14357 ClientSocketPoolManager::set_max_sockets_per_group(
14358 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14359 ClientSocketPoolManager::set_max_sockets_per_pool(
14360 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14361
14362 // Set up SSL request.
14363
14364 HttpRequestInfo ssl_request;
14365 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2314366 ssl_request.url = GURL("https://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214367
14368 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2314369 MockWrite(
14370 "GET / HTTP/1.1\r\n"
14371 "Host: www.example.org\r\n"
14372 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214373 };
14374 MockRead ssl_reads[] = {
14375 MockRead("HTTP/1.1 200 OK\r\n"),
14376 MockRead("Content-Length: 11\r\n\r\n"),
14377 MockRead("hello world"),
14378 MockRead(SYNCHRONOUS, OK),
14379 };
14380 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
14381 ssl_writes, arraysize(ssl_writes));
14382 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
14383
14384 SSLSocketDataProvider ssl(ASYNC, OK);
14385 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14386
14387 // Set up HTTP request.
14388
14389 HttpRequestInfo http_request;
14390 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2314391 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214392
14393 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2314394 MockWrite(
14395 "GET / HTTP/1.1\r\n"
14396 "Host: www.example.org\r\n"
14397 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214398 };
14399 MockRead http_reads[] = {
14400 MockRead("HTTP/1.1 200 OK\r\n"),
14401 MockRead("Content-Length: 7\r\n\r\n"),
14402 MockRead("falafel"),
14403 MockRead(SYNCHRONOUS, OK),
14404 };
14405 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
14406 http_writes, arraysize(http_writes));
14407 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14408
mmenke6b3af6e2015-09-12 02:06:0614409 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5214410
14411 // Start the SSL request.
14412 TestCompletionCallback ssl_callback;
14413 scoped_ptr<HttpTransaction> ssl_trans(
14414 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14415 ASSERT_EQ(ERR_IO_PENDING,
14416 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
14417 BoundNetLog()));
14418
14419 // Start the HTTP request. Pool should stall.
14420 TestCompletionCallback http_callback;
14421 scoped_ptr<HttpTransaction> http_trans(
14422 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14423 ASSERT_EQ(ERR_IO_PENDING,
14424 http_trans->Start(&http_request, http_callback.callback(),
14425 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4114426 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214427
14428 // Wait for response from SSL request.
14429 ASSERT_EQ(OK, ssl_callback.WaitForResult());
14430 std::string response_data;
14431 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
14432 EXPECT_EQ("hello world", response_data);
14433
14434 // The SSL socket should automatically be closed, so the HTTP request can
14435 // start.
dcheng48459ac22014-08-26 00:46:4114436 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
14437 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214438
14439 // The HTTP request can now complete.
14440 ASSERT_EQ(OK, http_callback.WaitForResult());
14441 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
14442 EXPECT_EQ("falafel", response_data);
14443
dcheng48459ac22014-08-26 00:46:4114444 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214445}
14446
14447// Tests that when a SSL connection is established but there's no corresponding
14448// request that needs it, the new socket is closed if the transport socket pool
14449// is stalled on the global socket limit.
14450TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
14451 ClientSocketPoolManager::set_max_sockets_per_group(
14452 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14453 ClientSocketPoolManager::set_max_sockets_per_pool(
14454 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14455
14456 // Set up an ssl request.
14457
14458 HttpRequestInfo ssl_request;
14459 ssl_request.method = "GET";
14460 ssl_request.url = GURL("https://www.foopy.com/");
14461
14462 // No data will be sent on the SSL socket.
14463 StaticSocketDataProvider ssl_data;
14464 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
14465
14466 SSLSocketDataProvider ssl(ASYNC, OK);
14467 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14468
14469 // Set up HTTP request.
14470
14471 HttpRequestInfo http_request;
14472 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2314473 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214474
14475 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2314476 MockWrite(
14477 "GET / HTTP/1.1\r\n"
14478 "Host: www.example.org\r\n"
14479 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214480 };
14481 MockRead http_reads[] = {
14482 MockRead("HTTP/1.1 200 OK\r\n"),
14483 MockRead("Content-Length: 7\r\n\r\n"),
14484 MockRead("falafel"),
14485 MockRead(SYNCHRONOUS, OK),
14486 };
14487 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
14488 http_writes, arraysize(http_writes));
14489 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14490
mmenke6b3af6e2015-09-12 02:06:0614491 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5214492
14493 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
14494 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2914495 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
14496 SSLConfig ssl_config;
[email protected]043b68c82013-08-22 23:41:5214497 session->ssl_config_service()->GetSSLConfig(&ssl_config);
mmenked1205bd2015-07-15 22:26:3514498 http_stream_factory->PreconnectStreams(1, ssl_request, ssl_config,
14499 ssl_config);
dcheng48459ac22014-08-26 00:46:4114500 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214501
14502 // Start the HTTP request. Pool should stall.
14503 TestCompletionCallback http_callback;
14504 scoped_ptr<HttpTransaction> http_trans(
14505 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14506 ASSERT_EQ(ERR_IO_PENDING,
14507 http_trans->Start(&http_request, http_callback.callback(),
14508 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4114509 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214510
14511 // The SSL connection will automatically be closed once the connection is
14512 // established, to let the HTTP request start.
14513 ASSERT_EQ(OK, http_callback.WaitForResult());
14514 std::string response_data;
14515 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
14516 EXPECT_EQ("falafel", response_data);
14517
dcheng48459ac22014-08-26 00:46:4114518 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214519}
14520
[email protected]02d74a02014-04-23 18:10:5414521TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
14522 ScopedVector<UploadElementReader> element_readers;
14523 element_readers.push_back(new UploadBytesElementReader("foo", 3));
mmenkecbc2b712014-10-09 20:29:0714524 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]02d74a02014-04-23 18:10:5414525
14526 HttpRequestInfo request;
14527 request.method = "POST";
14528 request.url = GURL("http://www.foo.com/");
14529 request.upload_data_stream = &upload_data_stream;
14530 request.load_flags = 0;
14531
mmenke6b3af6e2015-09-12 02:06:0614532 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414533 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114534 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414535 // Send headers successfully, but get an error while sending the body.
14536 MockWrite data_writes[] = {
14537 MockWrite("POST / HTTP/1.1\r\n"
14538 "Host: www.foo.com\r\n"
14539 "Connection: keep-alive\r\n"
14540 "Content-Length: 3\r\n\r\n"),
14541 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14542 };
14543
14544 MockRead data_reads[] = {
14545 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14546 MockRead("hello world"),
14547 MockRead(SYNCHRONOUS, OK),
14548 };
14549 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14550 arraysize(data_writes));
14551 session_deps_.socket_factory->AddSocketDataProvider(&data);
14552
14553 TestCompletionCallback callback;
14554
14555 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14556 EXPECT_EQ(ERR_IO_PENDING, rv);
14557
14558 rv = callback.WaitForResult();
14559 EXPECT_EQ(OK, rv);
14560
14561 const HttpResponseInfo* response = trans->GetResponseInfo();
14562 ASSERT_TRUE(response != NULL);
14563
14564 EXPECT_TRUE(response->headers.get() != NULL);
14565 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14566
14567 std::string response_data;
14568 rv = ReadTransaction(trans.get(), &response_data);
14569 EXPECT_EQ(OK, rv);
14570 EXPECT_EQ("hello world", response_data);
14571}
14572
14573// This test makes sure the retry logic doesn't trigger when reading an error
14574// response from a server that rejected a POST with a CONNECTION_RESET.
14575TEST_P(HttpNetworkTransactionTest,
14576 PostReadsErrorResponseAfterResetOnReusedSocket) {
mmenke6b3af6e2015-09-12 02:06:0614577 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414578 MockWrite data_writes[] = {
14579 MockWrite("GET / HTTP/1.1\r\n"
14580 "Host: www.foo.com\r\n"
14581 "Connection: keep-alive\r\n\r\n"),
14582 MockWrite("POST / HTTP/1.1\r\n"
14583 "Host: www.foo.com\r\n"
14584 "Connection: keep-alive\r\n"
14585 "Content-Length: 3\r\n\r\n"),
14586 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14587 };
14588
14589 MockRead data_reads[] = {
14590 MockRead("HTTP/1.1 200 Peachy\r\n"
14591 "Content-Length: 14\r\n\r\n"),
14592 MockRead("first response"),
14593 MockRead("HTTP/1.1 400 Not OK\r\n"
14594 "Content-Length: 15\r\n\r\n"),
14595 MockRead("second response"),
14596 MockRead(SYNCHRONOUS, OK),
14597 };
14598 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14599 arraysize(data_writes));
14600 session_deps_.socket_factory->AddSocketDataProvider(&data);
14601
14602 TestCompletionCallback callback;
14603 HttpRequestInfo request1;
14604 request1.method = "GET";
14605 request1.url = GURL("http://www.foo.com/");
14606 request1.load_flags = 0;
14607
14608 scoped_ptr<HttpTransaction> trans1(
dcheng48459ac22014-08-26 00:46:4114609 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414610 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
14611 EXPECT_EQ(ERR_IO_PENDING, rv);
14612
14613 rv = callback.WaitForResult();
14614 EXPECT_EQ(OK, rv);
14615
14616 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
14617 ASSERT_TRUE(response1 != NULL);
14618
14619 EXPECT_TRUE(response1->headers.get() != NULL);
14620 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
14621
14622 std::string response_data1;
14623 rv = ReadTransaction(trans1.get(), &response_data1);
14624 EXPECT_EQ(OK, rv);
14625 EXPECT_EQ("first response", response_data1);
14626 // Delete the transaction to release the socket back into the socket pool.
14627 trans1.reset();
14628
14629 ScopedVector<UploadElementReader> element_readers;
14630 element_readers.push_back(new UploadBytesElementReader("foo", 3));
mmenkecbc2b712014-10-09 20:29:0714631 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]02d74a02014-04-23 18:10:5414632
14633 HttpRequestInfo request2;
14634 request2.method = "POST";
14635 request2.url = GURL("http://www.foo.com/");
14636 request2.upload_data_stream = &upload_data_stream;
14637 request2.load_flags = 0;
14638
14639 scoped_ptr<HttpTransaction> trans2(
dcheng48459ac22014-08-26 00:46:4114640 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414641 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
14642 EXPECT_EQ(ERR_IO_PENDING, rv);
14643
14644 rv = callback.WaitForResult();
14645 EXPECT_EQ(OK, rv);
14646
14647 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
14648 ASSERT_TRUE(response2 != NULL);
14649
14650 EXPECT_TRUE(response2->headers.get() != NULL);
14651 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
14652
14653 std::string response_data2;
14654 rv = ReadTransaction(trans2.get(), &response_data2);
14655 EXPECT_EQ(OK, rv);
14656 EXPECT_EQ("second response", response_data2);
14657}
14658
14659TEST_P(HttpNetworkTransactionTest,
14660 PostReadsErrorResponseAfterResetPartialBodySent) {
14661 ScopedVector<UploadElementReader> element_readers;
14662 element_readers.push_back(new UploadBytesElementReader("foo", 3));
mmenkecbc2b712014-10-09 20:29:0714663 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]02d74a02014-04-23 18:10:5414664
14665 HttpRequestInfo request;
14666 request.method = "POST";
14667 request.url = GURL("http://www.foo.com/");
14668 request.upload_data_stream = &upload_data_stream;
14669 request.load_flags = 0;
14670
mmenke6b3af6e2015-09-12 02:06:0614671 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414672 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114673 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414674 // Send headers successfully, but get an error while sending the body.
14675 MockWrite data_writes[] = {
14676 MockWrite("POST / HTTP/1.1\r\n"
14677 "Host: www.foo.com\r\n"
14678 "Connection: keep-alive\r\n"
14679 "Content-Length: 3\r\n\r\n"
14680 "fo"),
14681 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14682 };
14683
14684 MockRead data_reads[] = {
14685 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14686 MockRead("hello world"),
14687 MockRead(SYNCHRONOUS, OK),
14688 };
14689 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14690 arraysize(data_writes));
14691 session_deps_.socket_factory->AddSocketDataProvider(&data);
14692
14693 TestCompletionCallback callback;
14694
14695 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14696 EXPECT_EQ(ERR_IO_PENDING, rv);
14697
14698 rv = callback.WaitForResult();
14699 EXPECT_EQ(OK, rv);
14700
14701 const HttpResponseInfo* response = trans->GetResponseInfo();
14702 ASSERT_TRUE(response != NULL);
14703
14704 EXPECT_TRUE(response->headers.get() != NULL);
14705 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14706
14707 std::string response_data;
14708 rv = ReadTransaction(trans.get(), &response_data);
14709 EXPECT_EQ(OK, rv);
14710 EXPECT_EQ("hello world", response_data);
14711}
14712
14713// This tests the more common case than the previous test, where headers and
14714// body are not merged into a single request.
14715TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
14716 ScopedVector<UploadElementReader> element_readers;
14717 element_readers.push_back(new UploadBytesElementReader("foo", 3));
mmenkecbc2b712014-10-09 20:29:0714718 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5414719
14720 HttpRequestInfo request;
14721 request.method = "POST";
14722 request.url = GURL("http://www.foo.com/");
14723 request.upload_data_stream = &upload_data_stream;
14724 request.load_flags = 0;
14725
mmenke6b3af6e2015-09-12 02:06:0614726 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414727 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114728 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414729 // Send headers successfully, but get an error while sending the body.
14730 MockWrite data_writes[] = {
14731 MockWrite("POST / HTTP/1.1\r\n"
14732 "Host: www.foo.com\r\n"
14733 "Connection: keep-alive\r\n"
14734 "Transfer-Encoding: chunked\r\n\r\n"),
14735 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14736 };
14737
14738 MockRead data_reads[] = {
14739 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14740 MockRead("hello world"),
14741 MockRead(SYNCHRONOUS, OK),
14742 };
14743 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14744 arraysize(data_writes));
14745 session_deps_.socket_factory->AddSocketDataProvider(&data);
14746
14747 TestCompletionCallback callback;
14748
14749 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14750 EXPECT_EQ(ERR_IO_PENDING, rv);
14751 // Make sure the headers are sent before adding a chunk. This ensures that
14752 // they can't be merged with the body in a single send. Not currently
14753 // necessary since a chunked body is never merged with headers, but this makes
14754 // the test more future proof.
14755 base::RunLoop().RunUntilIdle();
14756
mmenkecbc2b712014-10-09 20:29:0714757 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5414758
14759 rv = callback.WaitForResult();
14760 EXPECT_EQ(OK, rv);
14761
14762 const HttpResponseInfo* response = trans->GetResponseInfo();
14763 ASSERT_TRUE(response != NULL);
14764
14765 EXPECT_TRUE(response->headers.get() != NULL);
14766 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14767
14768 std::string response_data;
14769 rv = ReadTransaction(trans.get(), &response_data);
14770 EXPECT_EQ(OK, rv);
14771 EXPECT_EQ("hello world", response_data);
14772}
14773
14774TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
14775 ScopedVector<UploadElementReader> element_readers;
14776 element_readers.push_back(new UploadBytesElementReader("foo", 3));
mmenkecbc2b712014-10-09 20:29:0714777 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]02d74a02014-04-23 18:10:5414778
14779 HttpRequestInfo request;
14780 request.method = "POST";
14781 request.url = GURL("http://www.foo.com/");
14782 request.upload_data_stream = &upload_data_stream;
14783 request.load_flags = 0;
14784
mmenke6b3af6e2015-09-12 02:06:0614785 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414786 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114787 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414788
14789 MockWrite data_writes[] = {
14790 MockWrite("POST / HTTP/1.1\r\n"
14791 "Host: www.foo.com\r\n"
14792 "Connection: keep-alive\r\n"
14793 "Content-Length: 3\r\n\r\n"),
14794 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14795 };
14796
14797 MockRead data_reads[] = {
14798 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14799 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14800 MockRead("hello world"),
14801 MockRead(SYNCHRONOUS, OK),
14802 };
14803 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14804 arraysize(data_writes));
14805 session_deps_.socket_factory->AddSocketDataProvider(&data);
14806
14807 TestCompletionCallback callback;
14808
14809 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14810 EXPECT_EQ(ERR_IO_PENDING, rv);
14811
14812 rv = callback.WaitForResult();
14813 EXPECT_EQ(OK, rv);
14814
14815 const HttpResponseInfo* response = trans->GetResponseInfo();
14816 ASSERT_TRUE(response != NULL);
14817
14818 EXPECT_TRUE(response->headers.get() != NULL);
14819 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14820
14821 std::string response_data;
14822 rv = ReadTransaction(trans.get(), &response_data);
14823 EXPECT_EQ(OK, rv);
14824 EXPECT_EQ("hello world", response_data);
14825}
14826
14827TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
14828 ScopedVector<UploadElementReader> element_readers;
14829 element_readers.push_back(new UploadBytesElementReader("foo", 3));
mmenkecbc2b712014-10-09 20:29:0714830 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]02d74a02014-04-23 18:10:5414831
14832 HttpRequestInfo request;
14833 request.method = "POST";
14834 request.url = GURL("http://www.foo.com/");
14835 request.upload_data_stream = &upload_data_stream;
14836 request.load_flags = 0;
14837
mmenke6b3af6e2015-09-12 02:06:0614838 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414839 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114840 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414841 // Send headers successfully, but get an error while sending the body.
14842 MockWrite data_writes[] = {
14843 MockWrite("POST / HTTP/1.1\r\n"
14844 "Host: www.foo.com\r\n"
14845 "Connection: keep-alive\r\n"
14846 "Content-Length: 3\r\n\r\n"),
14847 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14848 };
14849
14850 MockRead data_reads[] = {
14851 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
14852 MockRead("hello world"),
14853 MockRead(SYNCHRONOUS, OK),
14854 };
14855 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14856 arraysize(data_writes));
14857 session_deps_.socket_factory->AddSocketDataProvider(&data);
14858
14859 TestCompletionCallback callback;
14860
14861 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14862 EXPECT_EQ(ERR_IO_PENDING, rv);
14863
14864 rv = callback.WaitForResult();
14865 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5414866}
14867
14868TEST_P(HttpNetworkTransactionTest,
14869 PostIgnoresNonErrorResponseAfterResetAnd100) {
14870 ScopedVector<UploadElementReader> element_readers;
14871 element_readers.push_back(new UploadBytesElementReader("foo", 3));
mmenkecbc2b712014-10-09 20:29:0714872 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]02d74a02014-04-23 18:10:5414873
14874 HttpRequestInfo request;
14875 request.method = "POST";
14876 request.url = GURL("http://www.foo.com/");
14877 request.upload_data_stream = &upload_data_stream;
14878 request.load_flags = 0;
14879
mmenke6b3af6e2015-09-12 02:06:0614880 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414881 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114882 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414883 // Send headers successfully, but get an error while sending the body.
14884 MockWrite data_writes[] = {
14885 MockWrite("POST / HTTP/1.1\r\n"
14886 "Host: www.foo.com\r\n"
14887 "Connection: keep-alive\r\n"
14888 "Content-Length: 3\r\n\r\n"),
14889 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14890 };
14891
14892 MockRead data_reads[] = {
14893 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14894 MockRead("HTTP/1.0 302 Redirect\r\n"),
14895 MockRead("Location: http://somewhere-else.com/\r\n"),
14896 MockRead("Content-Length: 0\r\n\r\n"),
14897 MockRead(SYNCHRONOUS, OK),
14898 };
14899 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14900 arraysize(data_writes));
14901 session_deps_.socket_factory->AddSocketDataProvider(&data);
14902
14903 TestCompletionCallback callback;
14904
14905 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14906 EXPECT_EQ(ERR_IO_PENDING, rv);
14907
14908 rv = callback.WaitForResult();
14909 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5414910}
14911
14912TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
14913 ScopedVector<UploadElementReader> element_readers;
14914 element_readers.push_back(new UploadBytesElementReader("foo", 3));
mmenkecbc2b712014-10-09 20:29:0714915 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]02d74a02014-04-23 18:10:5414916
14917 HttpRequestInfo request;
14918 request.method = "POST";
14919 request.url = GURL("http://www.foo.com/");
14920 request.upload_data_stream = &upload_data_stream;
14921 request.load_flags = 0;
14922
mmenke6b3af6e2015-09-12 02:06:0614923 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414924 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114925 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414926 // Send headers successfully, but get an error while sending the body.
14927 MockWrite data_writes[] = {
14928 MockWrite("POST / HTTP/1.1\r\n"
14929 "Host: www.foo.com\r\n"
14930 "Connection: keep-alive\r\n"
14931 "Content-Length: 3\r\n\r\n"),
14932 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14933 };
14934
14935 MockRead data_reads[] = {
14936 MockRead("HTTP 0.9 rocks!"),
14937 MockRead(SYNCHRONOUS, OK),
14938 };
14939 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14940 arraysize(data_writes));
14941 session_deps_.socket_factory->AddSocketDataProvider(&data);
14942
14943 TestCompletionCallback callback;
14944
14945 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14946 EXPECT_EQ(ERR_IO_PENDING, rv);
14947
14948 rv = callback.WaitForResult();
14949 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5414950}
14951
14952TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
14953 ScopedVector<UploadElementReader> element_readers;
14954 element_readers.push_back(new UploadBytesElementReader("foo", 3));
mmenkecbc2b712014-10-09 20:29:0714955 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]02d74a02014-04-23 18:10:5414956
14957 HttpRequestInfo request;
14958 request.method = "POST";
14959 request.url = GURL("http://www.foo.com/");
14960 request.upload_data_stream = &upload_data_stream;
14961 request.load_flags = 0;
14962
mmenke6b3af6e2015-09-12 02:06:0614963 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414964 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114965 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414966 // Send headers successfully, but get an error while sending the body.
14967 MockWrite data_writes[] = {
14968 MockWrite("POST / HTTP/1.1\r\n"
14969 "Host: www.foo.com\r\n"
14970 "Connection: keep-alive\r\n"
14971 "Content-Length: 3\r\n\r\n"),
14972 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14973 };
14974
14975 MockRead data_reads[] = {
14976 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
14977 MockRead(SYNCHRONOUS, OK),
14978 };
14979 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14980 arraysize(data_writes));
14981 session_deps_.socket_factory->AddSocketDataProvider(&data);
14982
14983 TestCompletionCallback callback;
14984
14985 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14986 EXPECT_EQ(ERR_IO_PENDING, rv);
14987
14988 rv = callback.WaitForResult();
14989 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5414990}
14991
Adam Rice425cf122015-01-19 06:18:2414992// Verify that proxy headers are not sent to the destination server when
14993// establishing a tunnel for a secure WebSocket connection.
14994TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
14995 HttpRequestInfo request;
14996 request.method = "GET";
bncce36dca22015-04-21 22:11:2314997 request.url = GURL("wss://www.example.org/");
Adam Rice425cf122015-01-19 06:18:2414998 AddWebSocketHeaders(&request.extra_headers);
14999
15000 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:0315001 session_deps_.proxy_service =
15002 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
Adam Rice425cf122015-01-19 06:18:2415003
mmenke6b3af6e2015-09-12 02:06:0615004 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2415005
15006 // Since a proxy is configured, try to establish a tunnel.
15007 MockWrite data_writes[] = {
15008 MockWrite(
bncce36dca22015-04-21 22:11:2315009 "CONNECT www.example.org:443 HTTP/1.1\r\n"
15010 "Host: www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415011 "Proxy-Connection: keep-alive\r\n\r\n"),
15012
15013 // After calling trans->RestartWithAuth(), this is the request we should
15014 // be issuing -- the final header line contains the credentials.
15015 MockWrite(
bncce36dca22015-04-21 22:11:2315016 "CONNECT www.example.org:443 HTTP/1.1\r\n"
15017 "Host: www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415018 "Proxy-Connection: keep-alive\r\n"
15019 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
15020
15021 MockWrite(
15022 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2315023 "Host: www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415024 "Connection: Upgrade\r\n"
15025 "Upgrade: websocket\r\n"
bncce36dca22015-04-21 22:11:2315026 "Origin: http://www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415027 "Sec-WebSocket-Version: 13\r\n"
15028 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
15029 };
15030
15031 // The proxy responds to the connect with a 407, using a persistent
15032 // connection.
15033 MockRead data_reads[] = {
15034 // No credentials.
15035 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
15036 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
mmenkee71e15332015-10-07 16:39:5415037 MockRead("Content-Length: 0\r\n"),
15038 MockRead("Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415039
15040 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15041
15042 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15043 MockRead("Upgrade: websocket\r\n"),
15044 MockRead("Connection: Upgrade\r\n"),
15045 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15046 };
15047
15048 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15049 arraysize(data_writes));
15050 session_deps_.socket_factory->AddSocketDataProvider(&data);
15051 SSLSocketDataProvider ssl(ASYNC, OK);
15052 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15053
15054 scoped_ptr<HttpTransaction> trans(
15055 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15056 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15057 trans->SetWebSocketHandshakeStreamCreateHelper(
15058 &websocket_stream_create_helper);
15059
15060 {
15061 TestCompletionCallback callback;
15062
15063 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15064 EXPECT_EQ(ERR_IO_PENDING, rv);
15065
15066 rv = callback.WaitForResult();
15067 EXPECT_EQ(OK, rv);
15068 }
15069
15070 const HttpResponseInfo* response = trans->GetResponseInfo();
15071 ASSERT_TRUE(response);
15072 ASSERT_TRUE(response->headers.get());
15073 EXPECT_EQ(407, response->headers->response_code());
15074
15075 {
15076 TestCompletionCallback callback;
15077
15078 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
15079 callback.callback());
15080 EXPECT_EQ(ERR_IO_PENDING, rv);
15081
15082 rv = callback.WaitForResult();
15083 EXPECT_EQ(OK, rv);
15084 }
15085
15086 response = trans->GetResponseInfo();
15087 ASSERT_TRUE(response);
15088 ASSERT_TRUE(response->headers.get());
15089
15090 EXPECT_EQ(101, response->headers->response_code());
15091
15092 trans.reset();
15093 session->CloseAllConnections();
15094}
15095
15096// Verify that proxy headers are not sent to the destination server when
15097// establishing a tunnel for an insecure WebSocket connection.
15098// This requires the authentication info to be injected into the auth cache
15099// due to crbug.com/395064
15100// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
15101TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
15102 HttpRequestInfo request;
15103 request.method = "GET";
bncce36dca22015-04-21 22:11:2315104 request.url = GURL("ws://www.example.org/");
Adam Rice425cf122015-01-19 06:18:2415105 AddWebSocketHeaders(&request.extra_headers);
15106
15107 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:0315108 session_deps_.proxy_service =
15109 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
Adam Rice425cf122015-01-19 06:18:2415110
mmenke6b3af6e2015-09-12 02:06:0615111 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2415112
15113 MockWrite data_writes[] = {
15114 // Try to establish a tunnel for the WebSocket connection, with
15115 // credentials. Because WebSockets have a separate set of socket pools,
15116 // they cannot and will not use the same TCP/IP connection as the
15117 // preflight HTTP request.
15118 MockWrite(
bncce36dca22015-04-21 22:11:2315119 "CONNECT www.example.org:80 HTTP/1.1\r\n"
15120 "Host: www.example.org:80\r\n"
Adam Rice425cf122015-01-19 06:18:2415121 "Proxy-Connection: keep-alive\r\n"
15122 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
15123
15124 MockWrite(
15125 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2315126 "Host: www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415127 "Connection: Upgrade\r\n"
15128 "Upgrade: websocket\r\n"
bncce36dca22015-04-21 22:11:2315129 "Origin: http://www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415130 "Sec-WebSocket-Version: 13\r\n"
15131 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
15132 };
15133
15134 MockRead data_reads[] = {
15135 // HTTP CONNECT with credentials.
15136 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15137
15138 // WebSocket connection established inside tunnel.
15139 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15140 MockRead("Upgrade: websocket\r\n"),
15141 MockRead("Connection: Upgrade\r\n"),
15142 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15143 };
15144
15145 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15146 arraysize(data_writes));
15147 session_deps_.socket_factory->AddSocketDataProvider(&data);
15148
15149 session->http_auth_cache()->Add(
15150 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
15151 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
15152
15153 scoped_ptr<HttpTransaction> trans(
15154 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15155 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15156 trans->SetWebSocketHandshakeStreamCreateHelper(
15157 &websocket_stream_create_helper);
15158
15159 TestCompletionCallback callback;
15160
15161 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15162 EXPECT_EQ(ERR_IO_PENDING, rv);
15163
15164 rv = callback.WaitForResult();
15165 EXPECT_EQ(OK, rv);
15166
15167 const HttpResponseInfo* response = trans->GetResponseInfo();
15168 ASSERT_TRUE(response);
15169 ASSERT_TRUE(response->headers.get());
15170
15171 EXPECT_EQ(101, response->headers->response_code());
15172
15173 trans.reset();
15174 session->CloseAllConnections();
15175}
15176
sclittlefb249892015-09-10 21:33:2215177TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
15178 ScopedVector<UploadElementReader> element_readers;
15179 element_readers.push_back(new UploadBytesElementReader("foo", 3));
15180 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
15181
15182 HttpRequestInfo request;
15183 request.method = "POST";
15184 request.url = GURL("http://www.foo.com/");
15185 request.upload_data_stream = &upload_data_stream;
15186
mmenke6b3af6e2015-09-12 02:06:0615187 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215188 scoped_ptr<HttpTransaction> trans(
15189 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15190 MockWrite data_writes[] = {
15191 MockWrite("POST / HTTP/1.1\r\n"
15192 "Host: www.foo.com\r\n"
15193 "Connection: keep-alive\r\n"
15194 "Content-Length: 3\r\n\r\n"),
15195 MockWrite("foo"),
15196 };
15197
15198 MockRead data_reads[] = {
15199 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15200 MockRead(SYNCHRONOUS, OK),
15201 };
15202 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15203 arraysize(data_writes));
15204 session_deps_.socket_factory->AddSocketDataProvider(&data);
15205
15206 TestCompletionCallback callback;
15207
15208 EXPECT_EQ(ERR_IO_PENDING,
15209 trans->Start(&request, callback.callback(), BoundNetLog()));
15210 EXPECT_EQ(OK, callback.WaitForResult());
15211
15212 std::string response_data;
15213 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15214
15215 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15216 trans->GetTotalSentBytes());
15217 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15218 trans->GetTotalReceivedBytes());
15219}
15220
15221TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
15222 ScopedVector<UploadElementReader> element_readers;
15223 element_readers.push_back(new UploadBytesElementReader("foo", 3));
15224 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
15225
15226 HttpRequestInfo request;
15227 request.method = "POST";
15228 request.url = GURL("http://www.foo.com/");
15229 request.upload_data_stream = &upload_data_stream;
15230
mmenke6b3af6e2015-09-12 02:06:0615231 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215232 scoped_ptr<HttpTransaction> trans(
15233 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15234 MockWrite data_writes[] = {
15235 MockWrite("POST / HTTP/1.1\r\n"
15236 "Host: www.foo.com\r\n"
15237 "Connection: keep-alive\r\n"
15238 "Content-Length: 3\r\n\r\n"),
15239 MockWrite("foo"),
15240 };
15241
15242 MockRead data_reads[] = {
15243 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
15244 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15245 MockRead(SYNCHRONOUS, OK),
15246 };
15247 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15248 arraysize(data_writes));
15249 session_deps_.socket_factory->AddSocketDataProvider(&data);
15250
15251 TestCompletionCallback callback;
15252
15253 EXPECT_EQ(ERR_IO_PENDING,
15254 trans->Start(&request, callback.callback(), BoundNetLog()));
15255 EXPECT_EQ(OK, callback.WaitForResult());
15256
15257 std::string response_data;
15258 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15259
15260 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15261 trans->GetTotalSentBytes());
15262 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15263 trans->GetTotalReceivedBytes());
15264}
15265
15266TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
15267 ScopedVector<UploadElementReader> element_readers;
15268 element_readers.push_back(new UploadBytesElementReader("foo", 3));
15269 ChunkedUploadDataStream upload_data_stream(0);
15270
15271 HttpRequestInfo request;
15272 request.method = "POST";
15273 request.url = GURL("http://www.foo.com/");
15274 request.upload_data_stream = &upload_data_stream;
15275
mmenke6b3af6e2015-09-12 02:06:0615276 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215277 scoped_ptr<HttpTransaction> trans(
15278 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15279 // Send headers successfully, but get an error while sending the body.
15280 MockWrite data_writes[] = {
15281 MockWrite("POST / HTTP/1.1\r\n"
15282 "Host: www.foo.com\r\n"
15283 "Connection: keep-alive\r\n"
15284 "Transfer-Encoding: chunked\r\n\r\n"),
15285 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
15286 };
15287
15288 MockRead data_reads[] = {
15289 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15290 MockRead(SYNCHRONOUS, OK),
15291 };
15292 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15293 arraysize(data_writes));
15294 session_deps_.socket_factory->AddSocketDataProvider(&data);
15295
15296 TestCompletionCallback callback;
15297
15298 EXPECT_EQ(ERR_IO_PENDING,
15299 trans->Start(&request, callback.callback(), BoundNetLog()));
15300
15301 base::RunLoop().RunUntilIdle();
15302 upload_data_stream.AppendData("f", 1, false);
15303
15304 base::RunLoop().RunUntilIdle();
15305 upload_data_stream.AppendData("oo", 2, true);
15306
15307 EXPECT_EQ(OK, callback.WaitForResult());
15308
15309 std::string response_data;
15310 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15311
15312 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15313 trans->GetTotalSentBytes());
15314 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15315 trans->GetTotalReceivedBytes());
15316}
15317
[email protected]89ceba9a2009-03-21 03:46:0615318} // namespace net