blob: 9bda396a3225f4361dca89c54ec0e53d53aa1f7e [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>
avibf0746c2015-12-09 19:53:1410#include <limits>
[email protected]5285d972011-10-18 18:56:3411#include <string>
dchengc7eeda422015-12-26 03:56:4812#include <utility>
[email protected]95d88ffe2010-02-04 21:25:3313#include <vector>
[email protected]77848d12008-11-14 00:00:2214
[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"
Avi Drissman13fc8932015-12-20 04:40:4620#include "base/macros.h"
[email protected]3b63f8f42011-03-28 01:54:1521#include "base/memory/scoped_ptr.h"
[email protected]bf828982013-08-14 18:01:4722#include "base/memory/weak_ptr.h"
[email protected]a34f61ee2014-03-18 20:59:4923#include "base/run_loop.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"
aberentbba302d2015-12-03 10:20:1947#include "net/http/http_auth_scheme.h"
Adam Rice425cf122015-01-19 06:18:2448#include "net/http/http_basic_state.h"
[email protected]0877e3d2009-10-17 22:29:5749#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5250#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5651#include "net/http/http_network_session_peer.h"
Adam Rice425cf122015-01-19 06:18:2452#include "net/http/http_request_headers.h"
[email protected]17291a022011-10-10 07:32:5353#include "net/http/http_server_properties_impl.h"
[email protected]0877e3d2009-10-17 22:29:5754#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3855#include "net/http/http_stream_factory.h"
Adam Rice425cf122015-01-19 06:18:2456#include "net/http/http_stream_parser.h"
[email protected]c41737d2014-05-14 07:47:1957#include "net/http/http_transaction_test_util.h"
eroman87c53d62015-04-02 06:51:0758#include "net/log/net_log.h"
vishal.b62985ca92015-04-17 08:45:5159#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4660#include "net/log/test_net_log_entry.h"
61#include "net/log/test_net_log_util.h"
sammc5dd160c2015-04-02 02:43:1362#include "net/proxy/mock_proxy_resolver.h"
[email protected]51fff29d2008-12-19 22:17:5363#include "net/proxy/proxy_config_service_fixed.h"
[email protected]e86839fd2013-08-14 18:29:0364#include "net/proxy/proxy_info.h"
[email protected]631f1322010-04-30 17:59:1165#include "net/proxy/proxy_resolver.h"
66#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4467#include "net/socket/client_socket_factory.h"
[email protected]483fa202013-05-14 01:07:0368#include "net/socket/client_socket_pool_manager.h"
ttuttle1f2d7e92015-04-28 16:17:4769#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0270#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0771#include "net/socket/next_proto.h"
[email protected]f7984fc62009-06-22 23:26:4472#include "net/socket/socket_test_util.h"
73#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5474#include "net/spdy/spdy_framer.h"
75#include "net/spdy/spdy_session.h"
76#include "net/spdy/spdy_session_pool.h"
[email protected]23e482282013-06-14 16:08:0277#include "net/spdy/spdy_test_util_common.h"
nharperb7441ef2016-01-25 23:54:1478#include "net/ssl/default_channel_id_store.h"
[email protected]536fd0b2013-03-14 17:41:5779#include "net/ssl/ssl_cert_request_info.h"
[email protected]e86839fd2013-08-14 18:29:0380#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:5781#include "net/ssl/ssl_config_service_defaults.h"
82#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:5483#include "net/ssl/ssl_private_key.h"
[email protected]6e7845ae2013-03-29 21:48:1184#include "net/test/cert_test_util.h"
[email protected]831e4a32013-11-14 02:14:4485#include "net/websockets/websocket_handshake_stream_base.h"
bncf4588402015-11-24 13:33:1886#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:5287#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1588#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:2789#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:5290
[email protected]ad65a3e2013-12-25 18:18:0191using base::ASCIIToUTF16;
92
initial.commit586acc5fe2008-07-26 22:42:5293//-----------------------------------------------------------------------------
94
ttuttle859dc7a2015-04-23 19:42:2995namespace net {
96
[email protected]13c8a092010-07-29 06:15:4497namespace {
98
rdsmithebb50aa2015-11-12 03:44:3899enum TestCase {
100 // Test using the SPDY/3.1 protocol.
101 kTestCaseSPDY31,
102
103 // Test using the HTTP/2 protocol, without specifying a stream
104 // dependency based on the RequestPriority.
105 kTestCaseHTTP2NoPriorityDependencies,
106
107 // Test using the HTTP/2 protocol, specifying a stream
108 // dependency based on the RequestPriority.
109 kTestCaseHTTP2PriorityDependencies
110};
111
[email protected]42cba2fb2013-03-29 19:58:57112const base::string16 kBar(ASCIIToUTF16("bar"));
113const base::string16 kBar2(ASCIIToUTF16("bar2"));
114const base::string16 kBar3(ASCIIToUTF16("bar3"));
115const base::string16 kBaz(ASCIIToUTF16("baz"));
116const base::string16 kFirst(ASCIIToUTF16("first"));
117const base::string16 kFoo(ASCIIToUTF16("foo"));
118const base::string16 kFoo2(ASCIIToUTF16("foo2"));
119const base::string16 kFoo3(ASCIIToUTF16("foo3"));
120const base::string16 kFou(ASCIIToUTF16("fou"));
121const base::string16 kSecond(ASCIIToUTF16("second"));
122const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
123const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44124
ttuttle859dc7a2015-04-23 19:42:29125int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
126 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
127 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02128}
129
ttuttle859dc7a2015-04-23 19:42:29130int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession* session) {
131 return session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
132 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02133}
134
ttuttle859dc7a2015-04-23 19:42:29135bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
136 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
137 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52138}
139
[email protected]f3da152d2012-06-02 01:00:57140// Takes in a Value created from a NetLogHttpResponseParameter, and returns
141// a JSONified list of headers as a single string. Uses single quotes instead
142// of double quotes for easier comparison. Returns false on failure.
[email protected]ea5ef4c2013-06-13 22:50:27143bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
[email protected]f3da152d2012-06-02 01:00:57144 if (!params)
145 return false;
[email protected]ea5ef4c2013-06-13 22:50:27146 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:57147 if (!params->GetList("headers", &header_list))
148 return false;
149 std::string double_quote_headers;
estade8d046462015-05-16 01:02:34150 base::JSONWriter::Write(*header_list, &double_quote_headers);
[email protected]466c9862013-12-03 22:05:28151 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
[email protected]f3da152d2012-06-02 01:00:57152 return true;
153}
154
[email protected]029c83b62013-01-24 05:28:20155// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
156// used.
ttuttle859dc7a2015-04-23 19:42:29157void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20158 EXPECT_TRUE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29159 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25160
[email protected]029c83b62013-01-24 05:28:20161 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
162 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
163
ttuttle859dc7a2015-04-23 19:42:29164 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20165 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25166
167 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25168
[email protected]3b23a222013-05-15 21:33:25169 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25170 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
171 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25172 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25173}
174
[email protected]029c83b62013-01-24 05:28:20175// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
176// used.
ttuttle859dc7a2015-04-23 19:42:29177void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25178 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20179 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29180 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20181
182 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
183 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
184
ttuttle859dc7a2015-04-23 19:42:29185 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
186 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20187 EXPECT_LE(load_timing_info.connect_timing.connect_end,
188 load_timing_info.send_start);
189
190 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20191
[email protected]3b23a222013-05-15 21:33:25192 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20193 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
194 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25195 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20196}
197
198// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
199// used.
ttuttle859dc7a2015-04-23 19:42:29200void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20201 EXPECT_TRUE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29202 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20203
ttuttle859dc7a2015-04-23 19:42:29204 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20205
206 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
207 EXPECT_LE(load_timing_info.proxy_resolve_start,
208 load_timing_info.proxy_resolve_end);
209 EXPECT_LE(load_timing_info.proxy_resolve_end,
210 load_timing_info.send_start);
211 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20212
[email protected]3b23a222013-05-15 21:33:25213 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20214 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
215 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25216 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20217}
218
219// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
220// used.
ttuttle859dc7a2015-04-23 19:42:29221void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20222 int connect_timing_flags) {
223 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29224 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20225
226 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
227 EXPECT_LE(load_timing_info.proxy_resolve_start,
228 load_timing_info.proxy_resolve_end);
229 EXPECT_LE(load_timing_info.proxy_resolve_end,
230 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29231 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
232 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20233 EXPECT_LE(load_timing_info.connect_timing.connect_end,
234 load_timing_info.send_start);
235
236 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20237
[email protected]3b23a222013-05-15 21:33:25238 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20239 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
240 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25241 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25242}
243
ttuttle859dc7a2015-04-23 19:42:29244void AddWebSocketHeaders(HttpRequestHeaders* headers) {
Adam Rice425cf122015-01-19 06:18:24245 headers->SetHeader("Connection", "Upgrade");
246 headers->SetHeader("Upgrade", "websocket");
bncce36dca22015-04-21 22:11:23247 headers->SetHeader("Origin", "http://www.example.org");
Adam Rice425cf122015-01-19 06:18:24248 headers->SetHeader("Sec-WebSocket-Version", "13");
249 headers->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
250}
251
mmenkee65e7af2015-10-13 17:16:42252scoped_ptr<HttpNetworkSession> CreateSession(
253 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34254 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14255}
256
[email protected]448d4ca52012-03-04 04:12:23257} // namespace
258
[email protected]23e482282013-06-14 16:08:02259class HttpNetworkTransactionTest
260 : public PlatformTest,
rdsmithebb50aa2015-11-12 03:44:38261 public ::testing::WithParamInterface<TestCase> {
[email protected]483fa202013-05-14 01:07:03262 public:
[email protected]23e482282013-06-14 16:08:02263 virtual ~HttpNetworkTransactionTest() {
[email protected]483fa202013-05-14 01:07:03264 // Important to restore the per-pool limit first, since the pool limit must
265 // always be greater than group limit, and the tests reduce both limits.
266 ClientSocketPoolManager::set_max_sockets_per_pool(
267 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
268 ClientSocketPoolManager::set_max_sockets_per_group(
269 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
rdsmithebb50aa2015-11-12 03:44:38270 SpdySession::SetPriorityDependencyDefaultForTesting(false);
[email protected]483fa202013-05-14 01:07:03271 }
272
[email protected]e3ceb682011-06-28 23:55:46273 protected:
[email protected]23e482282013-06-14 16:08:02274 HttpNetworkTransactionTest()
rdsmithebb50aa2015-11-12 03:44:38275 : spdy_util_(GetProtocol(), GetDependenciesFromPriority()),
276 session_deps_(GetProtocol()),
[email protected]483fa202013-05-14 01:07:03277 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
278 HttpNetworkSession::NORMAL_SOCKET_POOL)),
279 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
280 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
rdsmithebb50aa2015-11-12 03:44:38281 SpdySession::SetPriorityDependencyDefaultForTesting(
282 GetDependenciesFromPriority());
[email protected]483fa202013-05-14 01:07:03283 }
[email protected]bb88e1d32013-05-03 23:11:07284
[email protected]e3ceb682011-06-28 23:55:46285 struct SimpleGetHelperResult {
286 int rv;
287 std::string status_line;
288 std::string response_data;
sclittlefb249892015-09-10 21:33:22289 int64_t total_received_bytes;
290 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25291 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47292 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59293 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46294 };
295
dcheng67be2b1f2014-10-27 21:47:29296 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50297 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34298 base::MessageLoop::current()->RunUntilIdle();
[email protected]2ff8b312010-04-26 22:20:54299 }
300
dcheng67be2b1f2014-10-27 21:47:29301 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50302 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34303 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09304 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:34305 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09306 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50307 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34308 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09309 }
310
rdsmithebb50aa2015-11-12 03:44:38311 NextProto GetProtocol() const {
312 return GetParam() == kTestCaseSPDY31 ? kProtoSPDY31 : kProtoHTTP2;
313 }
314
315 bool GetDependenciesFromPriority() const {
316 return GetParam() == kTestCaseHTTP2PriorityDependencies;
317 }
318
bnc33b8cef42014-11-19 17:30:38319 const char* GetAlternateProtocolFromParam() {
rdsmithebb50aa2015-11-12 03:44:38320 return AlternateProtocolToString(
321 AlternateProtocolFromNextProto(GetProtocol()));
bnc33b8cef42014-11-19 17:30:38322 }
323
bncc958faa2015-07-31 18:14:52324 std::string GetAlternativeServiceHttpHeader() {
325 return std::string("Alt-Svc: ") + GetAlternateProtocolFromParam() +
326 "=\"www.example.com:443\"\r\n";
327 }
328
[email protected]8a0fc822013-06-27 20:52:43329 std::string GetAlternateProtocolHttpHeader() {
bnc33b8cef42014-11-19 17:30:38330 return std::string("Alternate-Protocol: 443:") +
bncc958faa2015-07-31 18:14:52331 GetAlternateProtocolFromParam() + "\r\n";
[email protected]8a0fc822013-06-27 20:52:43332 }
333
[email protected]202965992011-12-07 23:04:51334 // Either |write_failure| specifies a write failure or |read_failure|
335 // specifies a read failure when using a reused socket. In either case, the
336 // failure should cause the network transaction to resend the request, and the
337 // other argument should be NULL.
338 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
339 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52340
[email protected]a34f61ee2014-03-18 20:59:49341 // Either |write_failure| specifies a write failure or |read_failure|
342 // specifies a read failure when using a reused socket. In either case, the
343 // failure should cause the network transaction to resend the request, and the
344 // other argument should be NULL.
345 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10346 const MockRead* read_failure,
347 bool use_spdy);
[email protected]a34f61ee2014-03-18 20:59:49348
[email protected]5a60c8b2011-10-19 20:14:29349 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
350 size_t data_count) {
[email protected]ff007e162009-05-23 09:13:15351 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52352
[email protected]ff007e162009-05-23 09:13:15353 HttpRequestInfo request;
354 request.method = "GET";
bncce36dca22015-04-21 22:11:23355 request.url = GURL("http://www.example.org/");
[email protected]ff007e162009-05-23 09:13:15356 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52357
vishal.b62985ca92015-04-17 08:45:51358 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07359 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:42360 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:27361 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:41362 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:27363
[email protected]5a60c8b2011-10-19 20:14:29364 for (size_t i = 0; i < data_count; ++i) {
[email protected]bb88e1d32013-05-03 23:11:07365 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
[email protected]5a60c8b2011-10-19 20:14:29366 }
initial.commit586acc5fe2008-07-26 22:42:52367
[email protected]49639fa2011-12-20 23:22:41368 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52369
eroman24bc6a12015-05-06 19:55:48370 EXPECT_TRUE(log.bound().IsCapturing());
[email protected]49639fa2011-12-20 23:22:41371 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]ff007e162009-05-23 09:13:15372 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52373
[email protected]ff007e162009-05-23 09:13:15374 out.rv = callback.WaitForResult();
sclittlefb249892015-09-10 21:33:22375 out.total_received_bytes = trans->GetTotalReceivedBytes();
376 out.total_sent_bytes = trans->GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25377
378 // Even in the failure cases that use this function, connections are always
379 // successfully established before the error.
380 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
381 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
382
[email protected]ff007e162009-05-23 09:13:15383 if (out.rv != OK)
384 return out;
385
386 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50387 // Can't use ASSERT_* inside helper functions like this, so
388 // return an error.
[email protected]90499482013-06-01 00:39:50389 if (response == NULL || response->headers.get() == NULL) {
[email protected]fe2255a2011-09-20 19:37:50390 out.rv = ERR_UNEXPECTED;
391 return out;
392 }
[email protected]ff007e162009-05-23 09:13:15393 out.status_line = response->headers->GetStatusLine();
394
[email protected]80a09a82012-11-16 17:40:06395 EXPECT_EQ("127.0.0.1", response->socket_address.host());
396 EXPECT_EQ(80, response->socket_address.port());
[email protected]6d81b482011-02-22 19:47:19397
ttuttled9dbc652015-09-29 20:00:59398 bool got_endpoint =
399 trans->GetRemoteEndpoint(&out.remote_endpoint_after_start);
400 EXPECT_EQ(got_endpoint,
401 out.remote_endpoint_after_start.address().size() > 0);
402
[email protected]ff007e162009-05-23 09:13:15403 rv = ReadTransaction(trans.get(), &out.response_data);
404 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40405
mmenke43758e62015-05-04 21:09:46406 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:40407 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39408 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40409 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12410 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39411 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40412 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39413 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
414 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15415
[email protected]f3da152d2012-06-02 01:00:57416 std::string line;
417 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
418 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
419
[email protected]79e1fd62013-06-20 06:50:04420 HttpRequestHeaders request_headers;
421 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
422 std::string value;
423 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
bncce36dca22015-04-21 22:11:23424 EXPECT_EQ("www.example.org", value);
[email protected]79e1fd62013-06-20 06:50:04425 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
426 EXPECT_EQ("keep-alive", value);
427
428 std::string response_headers;
429 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
bncce36dca22015-04-21 22:11:23430 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
[email protected]79e1fd62013-06-20 06:50:04431 response_headers);
[email protected]3deb9a52010-11-11 00:24:40432
sclittlefb249892015-09-10 21:33:22433 out.total_received_bytes = trans->GetTotalReceivedBytes();
434 // The total number of sent bytes should not have changed.
435 EXPECT_EQ(out.total_sent_bytes, trans->GetTotalSentBytes());
436
ttuttle1f2d7e92015-04-28 16:17:47437 trans->GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47438 return out;
[email protected]ff007e162009-05-23 09:13:15439 }
initial.commit586acc5fe2008-07-26 22:42:52440
[email protected]5a60c8b2011-10-19 20:14:29441 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
442 size_t reads_count) {
sclittlefb249892015-09-10 21:33:22443 MockWrite data_writes[] = {
444 MockWrite("GET / HTTP/1.1\r\n"
445 "Host: www.example.org\r\n"
446 "Connection: keep-alive\r\n\r\n"),
447 };
[email protected]5a60c8b2011-10-19 20:14:29448
sclittlefb249892015-09-10 21:33:22449 StaticSocketDataProvider reads(data_reads, reads_count, data_writes,
450 arraysize(data_writes));
451 StaticSocketDataProvider* data[] = {&reads};
452 SimpleGetHelperResult out = SimpleGetHelperForData(data, 1);
453
454 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
455 out.total_sent_bytes);
456 return out;
[email protected]b8015c42013-12-24 15:18:19457 }
458
[email protected]ff007e162009-05-23 09:13:15459 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
460 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52461
[email protected]ff007e162009-05-23 09:13:15462 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07463
464 void BypassHostCacheOnRefreshHelper(int load_flags);
465
466 void CheckErrorIsPassedBack(int error, IoMode mode);
467
[email protected]4bd46222013-05-14 19:32:23468 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07469 SpdySessionDependencies session_deps_;
[email protected]483fa202013-05-14 01:07:03470
471 // Original socket limits. Some tests set these. Safest to always restore
472 // them once each test has been run.
473 int old_max_group_sockets_;
474 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15475};
[email protected]231d5a32008-09-13 00:45:27476
rdsmithebb50aa2015-11-12 03:44:38477INSTANTIATE_TEST_CASE_P(ProtoPlusDepend,
bnc57685ae62015-03-10 21:27:20478 HttpNetworkTransactionTest,
rdsmithebb50aa2015-11-12 03:44:38479 testing::Values(kTestCaseSPDY31,
480 kTestCaseHTTP2NoPriorityDependencies,
481 kTestCaseHTTP2PriorityDependencies));
[email protected]23e482282013-06-14 16:08:02482
[email protected]448d4ca52012-03-04 04:12:23483namespace {
484
[email protected]1826a402014-01-08 15:40:48485class BeforeNetworkStartHandler {
486 public:
487 explicit BeforeNetworkStartHandler(bool defer)
488 : defer_on_before_network_start_(defer),
489 observed_before_network_start_(false) {}
490
491 void OnBeforeNetworkStart(bool* defer) {
492 *defer = defer_on_before_network_start_;
493 observed_before_network_start_ = true;
494 }
495
496 bool observed_before_network_start() const {
497 return observed_before_network_start_;
498 }
499
500 private:
501 const bool defer_on_before_network_start_;
502 bool observed_before_network_start_;
503
504 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
505};
506
[email protected]597a1ab2014-06-26 08:12:27507class BeforeProxyHeadersSentHandler {
508 public:
509 BeforeProxyHeadersSentHandler()
510 : observed_before_proxy_headers_sent_(false) {}
511
[email protected]1252d42f2014-07-01 21:20:20512 void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
513 HttpRequestHeaders* request_headers) {
[email protected]597a1ab2014-06-26 08:12:27514 observed_before_proxy_headers_sent_ = true;
515 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
516 }
517
518 bool observed_before_proxy_headers_sent() const {
519 return observed_before_proxy_headers_sent_;
520 }
521
522 std::string observed_proxy_server_uri() const {
523 return observed_proxy_server_uri_;
524 }
525
526 private:
527 bool observed_before_proxy_headers_sent_;
528 std::string observed_proxy_server_uri_;
529
530 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler);
531};
532
[email protected]15a5ccf82008-10-23 19:57:43533// Fill |str| with a long header list that consumes >= |size| bytes.
534void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51535 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19536 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
537 const int sizeof_row = strlen(row);
538 const int num_rows = static_cast<int>(
539 ceil(static_cast<float>(size) / sizeof_row));
540 const int sizeof_data = num_rows * sizeof_row;
541 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43542 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51543
[email protected]4ddaf2502008-10-23 18:26:19544 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43545 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19546}
547
thakis84dff942015-07-28 20:47:38548#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29549// Alternative functions that eliminate randomness and dependency on the local
550// host name so that the generated NTLM messages are reproducible.
avibf0746c2015-12-09 19:53:14551void MockGenerateRandom1(uint8_t* output, size_t n) {
552 static const uint8_t bytes[] = {0x55, 0x29, 0x66, 0x26,
553 0x6b, 0x9c, 0x73, 0x54};
[email protected]385a4672009-03-11 22:21:29554 static size_t current_byte = 0;
555 for (size_t i = 0; i < n; ++i) {
556 output[i] = bytes[current_byte++];
557 current_byte %= arraysize(bytes);
558 }
559}
560
avibf0746c2015-12-09 19:53:14561void MockGenerateRandom2(uint8_t* output, size_t n) {
562 static const uint8_t bytes[] = {0x96, 0x79, 0x85, 0xe7, 0x49, 0x93,
563 0x70, 0xa1, 0x4e, 0xe7, 0x87, 0x45,
564 0x31, 0x5b, 0xd3, 0x1f};
[email protected]385a4672009-03-11 22:21:29565 static size_t current_byte = 0;
566 for (size_t i = 0; i < n; ++i) {
567 output[i] = bytes[current_byte++];
568 current_byte %= arraysize(bytes);
569 }
570}
571
[email protected]fe2bc6a2009-03-23 16:52:20572std::string MockGetHostName() {
573 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29574}
thakis84dff942015-07-28 20:47:38575#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29576
[email protected]e60e47a2010-07-14 03:37:18577template<typename ParentPool>
578class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31579 public:
[email protected]9e1bdd32011-02-03 21:48:34580 CaptureGroupNameSocketPool(HostResolver* host_resolver,
581 CertVerifier* cert_verifier);
[email protected]e60e47a2010-07-14 03:37:18582
[email protected]d80a4322009-08-14 07:07:49583 const std::string last_group_name_received() const {
584 return last_group_name_;
585 }
586
dmichaeld6e570d2014-12-18 22:30:57587 int RequestSocket(const std::string& group_name,
588 const void* socket_params,
589 RequestPriority priority,
590 ClientSocketHandle* handle,
591 const CompletionCallback& callback,
592 const BoundNetLog& net_log) override {
[email protected]04e5be32009-06-26 20:00:31593 last_group_name_ = group_name;
594 return ERR_IO_PENDING;
595 }
dmichaeld6e570d2014-12-18 22:30:57596 void CancelRequest(const std::string& group_name,
597 ClientSocketHandle* handle) override {}
598 void ReleaseSocket(const std::string& group_name,
599 scoped_ptr<StreamSocket> socket,
600 int id) override {}
601 void CloseIdleSockets() override {}
602 int IdleSocketCount() const override { return 0; }
603 int IdleSocketCountInGroup(const std::string& group_name) const override {
[email protected]04e5be32009-06-26 20:00:31604 return 0;
605 }
dmichaeld6e570d2014-12-18 22:30:57606 LoadState GetLoadState(const std::string& group_name,
607 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31608 return LOAD_STATE_IDLE;
609 }
dmichaeld6e570d2014-12-18 22:30:57610 base::TimeDelta ConnectionTimeout() const override {
[email protected]a796bcec2010-03-22 17:17:26611 return base::TimeDelta();
612 }
[email protected]d80a4322009-08-14 07:07:49613
614 private:
[email protected]04e5be32009-06-26 20:00:31615 std::string last_group_name_;
616};
617
[email protected]ab739042011-04-07 15:22:28618typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
619CaptureGroupNameTransportSocketPool;
[email protected]e772db3f2010-07-12 18:11:13620typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
621CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06622typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11623CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18624typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
625CaptureGroupNameSSLSocketPool;
626
rkaplowd90695c2015-03-25 22:12:41627template <typename ParentPool>
[email protected]e60e47a2010-07-14 03:37:18628CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34629 HostResolver* host_resolver,
630 CertVerifier* /* cert_verifier */)
rkaplowd90695c2015-03-25 22:12:41631 : ParentPool(0, 0, host_resolver, NULL, NULL) {
632}
[email protected]e60e47a2010-07-14 03:37:18633
hashimoto0d3e4fb2015-01-09 05:02:50634template <>
[email protected]2df19bb2010-08-25 20:13:46635CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
hashimotodae13b02015-01-15 04:28:21636 HostResolver* /* host_resolver */,
[email protected]9e1bdd32011-02-03 21:48:34637 CertVerifier* /* cert_verifier */)
rkaplowd90695c2015-03-25 22:12:41638 : HttpProxyClientSocketPool(0, 0, NULL, NULL, NULL) {
hashimoto0d3e4fb2015-01-09 05:02:50639}
[email protected]2df19bb2010-08-25 20:13:46640
[email protected]007b3f82013-04-09 08:46:45641template <>
[email protected]e60e47a2010-07-14 03:37:18642CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
hashimotodae13b02015-01-15 04:28:21643 HostResolver* /* host_resolver */,
[email protected]9e1bdd32011-02-03 21:48:34644 CertVerifier* cert_verifier)
[email protected]007b3f82013-04-09 08:46:45645 : SSLClientSocketPool(0,
646 0,
[email protected]007b3f82013-04-09 08:46:45647 cert_verifier,
648 NULL,
649 NULL,
[email protected]284303b62013-11-28 15:11:54650 NULL,
eranm6571b2b2014-12-03 15:53:23651 NULL,
[email protected]007b3f82013-04-09 08:46:45652 std::string(),
653 NULL,
654 NULL,
655 NULL,
656 NULL,
657 NULL,
[email protected]8e458552014-08-05 00:02:15658 NULL) {
659}
[email protected]2227c692010-05-04 15:36:11660
[email protected]231d5a32008-09-13 00:45:27661//-----------------------------------------------------------------------------
662
[email protected]79cb5c12011-09-12 13:12:04663// Helper functions for validating that AuthChallengeInfo's are correctly
664// configured for common cases.
665bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
666 if (!auth_challenge)
667 return false;
668 EXPECT_FALSE(auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:23669 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:04670 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19671 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04672 return true;
673}
674
675bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
676 if (!auth_challenge)
677 return false;
678 EXPECT_TRUE(auth_challenge->is_proxy);
679 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
680 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19681 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04682 return true;
683}
684
685bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
686 if (!auth_challenge)
687 return false;
688 EXPECT_FALSE(auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:23689 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:04690 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19691 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04692 return true;
693}
694
thakis84dff942015-07-28 20:47:38695#if defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04696bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
697 if (!auth_challenge)
698 return false;
699 EXPECT_FALSE(auth_challenge->is_proxy);
700 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
701 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19702 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04703 return true;
704}
thakis84dff942015-07-28 20:47:38705#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04706
[email protected]448d4ca52012-03-04 04:12:23707} // namespace
708
[email protected]23e482282013-06-14 16:08:02709TEST_P(HttpNetworkTransactionTest, Basic) {
mmenkee65e7af2015-10-13 17:16:42710 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:40711 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:41712 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]231d5a32008-09-13 00:45:27713}
714
[email protected]23e482282013-06-14 16:08:02715TEST_P(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27716 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35717 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
718 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06719 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27720 };
[email protected]31a2bfe2010-02-09 08:03:39721 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
722 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42723 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27724 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
725 EXPECT_EQ("hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22726 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
727 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47728 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59729
730 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27731}
732
733// Response with no status line.
[email protected]23e482282013-06-14 16:08:02734TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27735 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35736 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06737 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27738 };
[email protected]31a2bfe2010-02-09 08:03:39739 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
740 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42741 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27742 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
743 EXPECT_EQ("hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22744 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
745 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27746}
747
748// Allow up to 4 bytes of junk to precede status line.
[email protected]23e482282013-06-14 16:08:02749TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27750 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35751 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06752 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27753 };
[email protected]31a2bfe2010-02-09 08:03:39754 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
755 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42756 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27757 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
758 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22759 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
760 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27761}
762
763// Allow up to 4 bytes of junk to precede status line.
[email protected]23e482282013-06-14 16:08:02764TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27765 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35766 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06767 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27768 };
[email protected]31a2bfe2010-02-09 08:03:39769 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
770 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42771 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27772 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
773 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22774 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
775 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27776}
777
778// Beyond 4 bytes of slop and it should fail to find a status line.
[email protected]23e482282013-06-14 16:08:02779TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27780 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35781 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06782 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27783 };
[email protected]31a2bfe2010-02-09 08:03:39784 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
785 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42786 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25787 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
788 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
sclittlefb249892015-09-10 21:33:22789 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
790 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27791}
792
793// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
[email protected]23e482282013-06-14 16:08:02794TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27795 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35796 MockRead("\n"),
797 MockRead("\n"),
798 MockRead("Q"),
799 MockRead("J"),
800 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06801 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27802 };
[email protected]31a2bfe2010-02-09 08:03:39803 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
804 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42805 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27806 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
807 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22808 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
809 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27810}
811
812// Close the connection before enough bytes to have a status line.
[email protected]23e482282013-06-14 16:08:02813TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27814 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35815 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06816 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27817 };
[email protected]31a2bfe2010-02-09 08:03:39818 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
819 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42820 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27821 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
822 EXPECT_EQ("HTT", out.response_data);
sclittlefb249892015-09-10 21:33:22823 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
824 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:52825}
826
[email protected]f9d44aa2008-09-23 23:57:17827// Simulate a 204 response, lacking a Content-Length header, sent over a
828// persistent connection. The response should still terminate since a 204
829// cannot have a response body.
[email protected]23e482282013-06-14 16:08:02830TEST_P(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:19831 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:17832 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35833 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:19834 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:06835 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:17836 };
[email protected]31a2bfe2010-02-09 08:03:39837 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
838 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42839 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17840 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
841 EXPECT_EQ("", out.response_data);
sclittlefb249892015-09-10 21:33:22842 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
843 int64_t response_size = reads_size - strlen(junk);
844 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:17845}
846
[email protected]0877e3d2009-10-17 22:29:57847// A simple request using chunked encoding with some extra data after.
[email protected]23e482282013-06-14 16:08:02848TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:19849 std::string final_chunk = "0\r\n\r\n";
850 std::string extra_data = "HTTP/1.1 200 OK\r\n";
851 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:57852 MockRead data_reads[] = {
853 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
854 MockRead("5\r\nHello\r\n"),
855 MockRead("1\r\n"),
856 MockRead(" \r\n"),
857 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:19858 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:06859 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:57860 };
[email protected]31a2bfe2010-02-09 08:03:39861 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
862 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57863 EXPECT_EQ(OK, out.rv);
864 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
865 EXPECT_EQ("Hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22866 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
867 int64_t response_size = reads_size - extra_data.size();
868 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:57869}
870
[email protected]9fe44f52010-09-23 18:36:00871// Next tests deal with http://crbug.com/56344.
872
[email protected]23e482282013-06-14 16:08:02873TEST_P(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00874 MultipleContentLengthHeadersNoTransferEncoding) {
875 MockRead data_reads[] = {
876 MockRead("HTTP/1.1 200 OK\r\n"),
877 MockRead("Content-Length: 10\r\n"),
878 MockRead("Content-Length: 5\r\n\r\n"),
879 };
880 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
881 arraysize(data_reads));
882 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
883}
884
[email protected]23e482282013-06-14 16:08:02885TEST_P(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04886 DuplicateContentLengthHeadersNoTransferEncoding) {
887 MockRead data_reads[] = {
888 MockRead("HTTP/1.1 200 OK\r\n"),
889 MockRead("Content-Length: 5\r\n"),
890 MockRead("Content-Length: 5\r\n\r\n"),
891 MockRead("Hello"),
892 };
893 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
894 arraysize(data_reads));
895 EXPECT_EQ(OK, out.rv);
896 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
897 EXPECT_EQ("Hello", out.response_data);
898}
899
[email protected]23e482282013-06-14 16:08:02900TEST_P(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04901 ComplexContentLengthHeadersNoTransferEncoding) {
902 // More than 2 dupes.
903 {
904 MockRead data_reads[] = {
905 MockRead("HTTP/1.1 200 OK\r\n"),
906 MockRead("Content-Length: 5\r\n"),
907 MockRead("Content-Length: 5\r\n"),
908 MockRead("Content-Length: 5\r\n\r\n"),
909 MockRead("Hello"),
910 };
911 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
912 arraysize(data_reads));
913 EXPECT_EQ(OK, out.rv);
914 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
915 EXPECT_EQ("Hello", out.response_data);
916 }
917 // HTTP/1.0
918 {
919 MockRead data_reads[] = {
920 MockRead("HTTP/1.0 200 OK\r\n"),
921 MockRead("Content-Length: 5\r\n"),
922 MockRead("Content-Length: 5\r\n"),
923 MockRead("Content-Length: 5\r\n\r\n"),
924 MockRead("Hello"),
925 };
926 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
927 arraysize(data_reads));
928 EXPECT_EQ(OK, out.rv);
929 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
930 EXPECT_EQ("Hello", out.response_data);
931 }
932 // 2 dupes and one mismatched.
933 {
934 MockRead data_reads[] = {
935 MockRead("HTTP/1.1 200 OK\r\n"),
936 MockRead("Content-Length: 10\r\n"),
937 MockRead("Content-Length: 10\r\n"),
938 MockRead("Content-Length: 5\r\n\r\n"),
939 };
940 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
941 arraysize(data_reads));
942 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
943 }
944}
945
[email protected]23e482282013-06-14 16:08:02946TEST_P(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00947 MultipleContentLengthHeadersTransferEncoding) {
948 MockRead data_reads[] = {
949 MockRead("HTTP/1.1 200 OK\r\n"),
950 MockRead("Content-Length: 666\r\n"),
951 MockRead("Content-Length: 1337\r\n"),
952 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
953 MockRead("5\r\nHello\r\n"),
954 MockRead("1\r\n"),
955 MockRead(" \r\n"),
956 MockRead("5\r\nworld\r\n"),
957 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:06958 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:00959 };
960 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
961 arraysize(data_reads));
962 EXPECT_EQ(OK, out.rv);
963 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
964 EXPECT_EQ("Hello world", out.response_data);
965}
966
[email protected]1628fe92011-10-04 23:04:55967// Next tests deal with http://crbug.com/98895.
968
969// Checks that a single Content-Disposition header results in no error.
[email protected]23e482282013-06-14 16:08:02970TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:55971 MockRead data_reads[] = {
972 MockRead("HTTP/1.1 200 OK\r\n"),
973 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
974 MockRead("Content-Length: 5\r\n\r\n"),
975 MockRead("Hello"),
976 };
977 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
978 arraysize(data_reads));
979 EXPECT_EQ(OK, out.rv);
980 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
981 EXPECT_EQ("Hello", out.response_data);
982}
983
[email protected]54a9c6e52012-03-21 20:10:59984// Checks that two identical Content-Disposition headers result in no error.
[email protected]23e482282013-06-14 16:08:02985TEST_P(HttpNetworkTransactionTest,
[email protected]54a9c6e52012-03-21 20:10:59986 TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:55987 MockRead data_reads[] = {
988 MockRead("HTTP/1.1 200 OK\r\n"),
989 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
990 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
991 MockRead("Content-Length: 5\r\n\r\n"),
992 MockRead("Hello"),
993 };
994 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
995 arraysize(data_reads));
[email protected]54a9c6e52012-03-21 20:10:59996 EXPECT_EQ(OK, out.rv);
997 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
998 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:55999}
1000
1001// Checks that two distinct Content-Disposition headers result in an error.
[email protected]23e482282013-06-14 16:08:021002TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551003 MockRead data_reads[] = {
1004 MockRead("HTTP/1.1 200 OK\r\n"),
1005 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1006 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1007 MockRead("Content-Length: 5\r\n\r\n"),
1008 MockRead("Hello"),
1009 };
1010 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1011 arraysize(data_reads));
1012 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
1013}
1014
[email protected]54a9c6e52012-03-21 20:10:591015// Checks that two identical Location headers result in no error.
1016// Also tests Location header behavior.
[email protected]23e482282013-06-14 16:08:021017TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551018 MockRead data_reads[] = {
1019 MockRead("HTTP/1.1 302 Redirect\r\n"),
1020 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591021 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551022 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061023 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551024 };
1025
1026 HttpRequestInfo request;
1027 request.method = "GET";
1028 request.url = GURL("http://redirect.com/");
1029 request.load_flags = 0;
1030
mmenkee65e7af2015-10-13 17:16:421031 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1628fe92011-10-04 23:04:551032 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411033 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]1628fe92011-10-04 23:04:551034
1035 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071036 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551037
[email protected]49639fa2011-12-20 23:22:411038 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551039
[email protected]49639fa2011-12-20 23:22:411040 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1628fe92011-10-04 23:04:551041 EXPECT_EQ(ERR_IO_PENDING, rv);
1042
1043 EXPECT_EQ(OK, callback.WaitForResult());
1044
1045 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501046 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
[email protected]1628fe92011-10-04 23:04:551047 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1048 std::string url;
1049 EXPECT_TRUE(response->headers->IsRedirect(&url));
1050 EXPECT_EQ("http://good.com/", url);
[email protected]d8fc4722014-06-13 13:17:151051 EXPECT_TRUE(response->proxy_server.IsEmpty());
[email protected]1628fe92011-10-04 23:04:551052}
1053
[email protected]1628fe92011-10-04 23:04:551054// Checks that two distinct Location headers result in an error.
[email protected]23e482282013-06-14 16:08:021055TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551056 MockRead data_reads[] = {
1057 MockRead("HTTP/1.1 302 Redirect\r\n"),
1058 MockRead("Location: http://good.com/\r\n"),
1059 MockRead("Location: http://evil.com/\r\n"),
1060 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061061 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551062 };
1063 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1064 arraysize(data_reads));
1065 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
1066}
1067
[email protected]ef0faf2e72009-03-05 23:27:231068// Do a request using the HEAD method. Verify that we don't try to read the
1069// message body (since HEAD has none).
[email protected]23e482282013-06-14 16:08:021070TEST_P(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421071 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231072 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231073 request.url = GURL("http://www.example.org/");
[email protected]ef0faf2e72009-03-05 23:27:231074 request.load_flags = 0;
1075
mmenkee65e7af2015-10-13 17:16:421076 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271077 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411078 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]597a1ab2014-06-26 08:12:271079 BeforeProxyHeadersSentHandler proxy_headers_handler;
1080 trans->SetBeforeProxyHeadersSentCallback(
1081 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
1082 base::Unretained(&proxy_headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271083
[email protected]ef0faf2e72009-03-05 23:27:231084 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131085 MockWrite("HEAD / HTTP/1.1\r\n"
1086 "Host: www.example.org\r\n"
1087 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231088 };
1089 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231090 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1091 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231092
mmenked39192ee2015-12-09 00:57:231093 // No response body because the test stops reading here.
1094 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231095 };
1096
[email protected]31a2bfe2010-02-09 08:03:391097 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1098 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:071099 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231100
[email protected]49639fa2011-12-20 23:22:411101 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231102
[email protected]49639fa2011-12-20 23:22:411103 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421104 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:231105
1106 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421107 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:231108
[email protected]1c773ea12009-04-28 19:58:421109 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501110 ASSERT_TRUE(response != NULL);
[email protected]ef0faf2e72009-03-05 23:27:231111
1112 // Check that the headers got parsed.
[email protected]90499482013-06-01 00:39:501113 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]ef0faf2e72009-03-05 23:27:231114 EXPECT_EQ(1234, response->headers->GetContentLength());
1115 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151116 EXPECT_TRUE(response->proxy_server.IsEmpty());
[email protected]597a1ab2014-06-26 08:12:271117 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
[email protected]ef0faf2e72009-03-05 23:27:231118
1119 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101120 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231121 bool has_server_header = response->headers->EnumerateHeader(
1122 &iter, "Server", &server_header);
1123 EXPECT_TRUE(has_server_header);
1124 EXPECT_EQ("Blah", server_header);
1125
1126 // Reading should give EOF right away, since there is no message body
1127 // (despite non-zero content-length).
1128 std::string response_data;
1129 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421130 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:231131 EXPECT_EQ("", response_data);
1132}
1133
[email protected]23e482282013-06-14 16:08:021134TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
mmenkee65e7af2015-10-13 17:16:421135 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521136
1137 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351138 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1139 MockRead("hello"),
1140 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1141 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061142 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521143 };
[email protected]31a2bfe2010-02-09 08:03:391144 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071145 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521146
[email protected]0b0bf032010-09-21 18:08:501147 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521148 "hello", "world"
1149 };
1150
1151 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421152 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521153 request.method = "GET";
bncce36dca22015-04-21 22:11:231154 request.url = GURL("http://www.example.org/");
initial.commit586acc5fe2008-07-26 22:42:521155 request.load_flags = 0;
1156
[email protected]262eec82013-03-19 21:01:361157 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501158 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271159
[email protected]49639fa2011-12-20 23:22:411160 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521161
[email protected]49639fa2011-12-20 23:22:411162 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421163 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521164
1165 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421166 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521167
[email protected]1c773ea12009-04-28 19:58:421168 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501169 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521170
[email protected]90499482013-06-01 00:39:501171 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251172 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151173 EXPECT_TRUE(response->proxy_server.IsEmpty());
initial.commit586acc5fe2008-07-26 22:42:521174
1175 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571176 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421177 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251178 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521179 }
1180}
1181
[email protected]23e482282013-06-14 16:08:021182TEST_P(HttpNetworkTransactionTest, Ignores100) {
olli.raula6df48b2a2015-11-26 07:40:221183 std::vector<scoped_ptr<UploadElementReader>> element_readers;
1184 element_readers.push_back(
1185 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
1186 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271187
[email protected]1c773ea12009-04-28 19:58:421188 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521189 request.method = "POST";
1190 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271191 request.upload_data_stream = &upload_data_stream;
initial.commit586acc5fe2008-07-26 22:42:521192 request.load_flags = 0;
1193
mmenkee65e7af2015-10-13 17:16:421194 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271195 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411196 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271197
initial.commit586acc5fe2008-07-26 22:42:521198 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351199 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1200 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1201 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061202 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521203 };
[email protected]31a2bfe2010-02-09 08:03:391204 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071205 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521206
[email protected]49639fa2011-12-20 23:22:411207 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521208
[email protected]49639fa2011-12-20 23:22:411209 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421210 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521211
1212 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421213 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521214
[email protected]1c773ea12009-04-28 19:58:421215 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501216 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521217
[email protected]90499482013-06-01 00:39:501218 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251219 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521220
1221 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571222 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421223 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251224 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521225}
1226
[email protected]3a2d3662009-03-27 03:49:141227// This test is almost the same as Ignores100 above, but the response contains
1228// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571229// HTTP/1.1 and the two status headers are read in one read.
[email protected]23e482282013-06-14 16:08:021230TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421231 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141232 request.method = "GET";
1233 request.url = GURL("http://www.foo.com/");
1234 request.load_flags = 0;
1235
mmenkee65e7af2015-10-13 17:16:421236 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271237 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411238 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271239
[email protected]3a2d3662009-03-27 03:49:141240 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571241 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1242 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141243 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061244 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141245 };
[email protected]31a2bfe2010-02-09 08:03:391246 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071247 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141248
[email protected]49639fa2011-12-20 23:22:411249 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141250
[email protected]49639fa2011-12-20 23:22:411251 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421252 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:141253
1254 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421255 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:141256
[email protected]1c773ea12009-04-28 19:58:421257 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501258 ASSERT_TRUE(response != NULL);
[email protected]3a2d3662009-03-27 03:49:141259
[email protected]90499482013-06-01 00:39:501260 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3a2d3662009-03-27 03:49:141261 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1262
1263 std::string response_data;
1264 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421265 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:141266 EXPECT_EQ("hello world", response_data);
1267}
1268
[email protected]23e482282013-06-14 16:08:021269TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081270 HttpRequestInfo request;
1271 request.method = "POST";
1272 request.url = GURL("http://www.foo.com/");
1273 request.load_flags = 0;
1274
mmenkee65e7af2015-10-13 17:16:421275 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
zmo9528c9f42015-08-04 22:12:081276 scoped_ptr<HttpTransaction> trans(
1277 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1278
1279 MockRead data_reads[] = {
1280 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1281 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381282 };
zmo9528c9f42015-08-04 22:12:081283 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1284 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381285
zmo9528c9f42015-08-04 22:12:081286 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381287
zmo9528c9f42015-08-04 22:12:081288 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1289 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ee9410e72010-01-07 01:42:381290
zmo9528c9f42015-08-04 22:12:081291 rv = callback.WaitForResult();
1292 EXPECT_EQ(OK, rv);
[email protected]ee9410e72010-01-07 01:42:381293
zmo9528c9f42015-08-04 22:12:081294 std::string response_data;
1295 rv = ReadTransaction(trans.get(), &response_data);
1296 EXPECT_EQ(OK, rv);
1297 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381298}
1299
[email protected]23e482282013-06-14 16:08:021300TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381301 HttpRequestInfo request;
1302 request.method = "POST";
1303 request.url = GURL("http://www.foo.com/");
1304 request.load_flags = 0;
1305
mmenkee65e7af2015-10-13 17:16:421306 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271307 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411308 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271309
[email protected]ee9410e72010-01-07 01:42:381310 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061311 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381312 };
[email protected]31a2bfe2010-02-09 08:03:391313 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071314 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381315
[email protected]49639fa2011-12-20 23:22:411316 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381317
[email protected]49639fa2011-12-20 23:22:411318 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:381319 EXPECT_EQ(ERR_IO_PENDING, rv);
1320
1321 rv = callback.WaitForResult();
1322 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1323}
1324
[email protected]23e482282013-06-14 16:08:021325void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511326 const MockWrite* write_failure,
1327 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421328 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521329 request.method = "GET";
1330 request.url = GURL("http://www.foo.com/");
1331 request.load_flags = 0;
1332
vishal.b62985ca92015-04-17 08:45:511333 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071334 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421335 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271336
[email protected]202965992011-12-07 23:04:511337 // Written data for successfully sending both requests.
1338 MockWrite data1_writes[] = {
1339 MockWrite("GET / HTTP/1.1\r\n"
1340 "Host: www.foo.com\r\n"
1341 "Connection: keep-alive\r\n\r\n"),
1342 MockWrite("GET / HTTP/1.1\r\n"
1343 "Host: www.foo.com\r\n"
1344 "Connection: keep-alive\r\n\r\n")
1345 };
1346
1347 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521348 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351349 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1350 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061351 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521352 };
[email protected]202965992011-12-07 23:04:511353
1354 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491355 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511356 data1_writes[1] = *write_failure;
1357 } else {
1358 ASSERT_TRUE(read_failure);
1359 data1_reads[2] = *read_failure;
1360 }
1361
1362 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1363 data1_writes, arraysize(data1_writes));
[email protected]bb88e1d32013-05-03 23:11:071364 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521365
1366 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351367 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1368 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061369 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521370 };
[email protected]31a2bfe2010-02-09 08:03:391371 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071372 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521373
thestig9d3bb0c2015-01-24 00:49:511374 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521375 "hello", "world"
1376 };
1377
avibf0746c2015-12-09 19:53:141378 uint32_t first_socket_log_id = NetLog::Source::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521379 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411380 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521381
[email protected]262eec82013-03-19 21:01:361382 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501383 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
initial.commit586acc5fe2008-07-26 22:42:521384
[email protected]49639fa2011-12-20 23:22:411385 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421386 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521387
1388 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421389 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521390
[email protected]58e32bb2013-01-21 18:23:251391 LoadTimingInfo load_timing_info;
1392 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1393 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1394 if (i == 0) {
1395 first_socket_log_id = load_timing_info.socket_log_id;
1396 } else {
1397 // The second request should be using a new socket.
1398 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1399 }
1400
[email protected]1c773ea12009-04-28 19:58:421401 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501402 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521403
[email protected]90499482013-06-01 00:39:501404 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251405 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521406
1407 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571408 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421409 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251410 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521411 }
1412}
[email protected]3d2a59b2008-09-26 19:44:251413
[email protected]a34f61ee2014-03-18 20:59:491414void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1415 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101416 const MockRead* read_failure,
1417 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491418 HttpRequestInfo request;
1419 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101420 request.url = GURL("https://www.foo.com/");
[email protected]a34f61ee2014-03-18 20:59:491421 request.load_flags = 0;
1422
vishal.b62985ca92015-04-17 08:45:511423 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491424 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421425 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491426
[email protected]09356c652014-03-25 15:36:101427 SSLSocketDataProvider ssl1(ASYNC, OK);
1428 SSLSocketDataProvider ssl2(ASYNC, OK);
1429 if (use_spdy) {
rdsmithebb50aa2015-11-12 03:44:381430 ssl1.SetNextProto(GetProtocol());
1431 ssl2.SetNextProto(GetProtocol());
[email protected]09356c652014-03-25 15:36:101432 }
1433 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1434 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491435
[email protected]09356c652014-03-25 15:36:101436 // SPDY versions of the request and response.
1437 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1438 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1439 scoped_ptr<SpdyFrame> spdy_response(
1440 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1441 scoped_ptr<SpdyFrame> spdy_data(
1442 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
[email protected]a34f61ee2014-03-18 20:59:491443
[email protected]09356c652014-03-25 15:36:101444 // HTTP/1.1 versions of the request and response.
1445 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1446 "Host: www.foo.com\r\n"
1447 "Connection: keep-alive\r\n\r\n";
1448 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1449 const char kHttpData[] = "hello";
1450
1451 std::vector<MockRead> data1_reads;
1452 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491453 if (write_failure) {
1454 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101455 data1_writes.push_back(*write_failure);
1456 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491457 } else {
1458 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101459 if (use_spdy) {
1460 data1_writes.push_back(CreateMockWrite(*spdy_request));
1461 } else {
1462 data1_writes.push_back(MockWrite(kHttpRequest));
1463 }
1464 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491465 }
1466
[email protected]09356c652014-03-25 15:36:101467 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1468 &data1_writes[0], data1_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491469 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1470
[email protected]09356c652014-03-25 15:36:101471 std::vector<MockRead> data2_reads;
1472 std::vector<MockWrite> data2_writes;
1473
1474 if (use_spdy) {
1475 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1476
1477 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1478 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1479 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1480 } else {
1481 data2_writes.push_back(
1482 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1483
1484 data2_reads.push_back(
1485 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1486 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1487 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1488 }
rch8e6c6c42015-05-01 14:05:131489 SequencedSocketData data2(&data2_reads[0], data2_reads.size(),
1490 &data2_writes[0], data2_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491491 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1492
1493 // Preconnect a socket.
ttuttle859dc7a2015-04-23 19:42:291494 SSLConfig ssl_config;
[email protected]a34f61ee2014-03-18 20:59:491495 session->ssl_config_service()->GetSSLConfig(&ssl_config);
bnc1f295372015-10-21 23:24:221496 session->GetAlpnProtos(&ssl_config.alpn_protos);
1497 session->GetNpnProtos(&ssl_config.npn_protos);
mmenked1205bd2015-07-15 22:26:351498 session->http_stream_factory()->PreconnectStreams(1, request, ssl_config,
1499 ssl_config);
[email protected]a34f61ee2014-03-18 20:59:491500 // Wait for the preconnect to complete.
1501 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1502 base::RunLoop().RunUntilIdle();
[email protected]09356c652014-03-25 15:36:101503 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491504
1505 // Make the request.
1506 TestCompletionCallback callback;
1507
1508 scoped_ptr<HttpTransaction> trans(
1509 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1510
1511 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1512 EXPECT_EQ(ERR_IO_PENDING, rv);
1513
1514 rv = callback.WaitForResult();
1515 EXPECT_EQ(OK, rv);
1516
1517 LoadTimingInfo load_timing_info;
1518 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101519 TestLoadTimingNotReused(
1520 load_timing_info,
1521 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491522
1523 const HttpResponseInfo* response = trans->GetResponseInfo();
1524 ASSERT_TRUE(response != NULL);
1525
1526 EXPECT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:021527 if (response->was_fetched_via_spdy) {
1528 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1529 } else {
1530 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1531 }
[email protected]a34f61ee2014-03-18 20:59:491532
1533 std::string response_data;
1534 rv = ReadTransaction(trans.get(), &response_data);
1535 EXPECT_EQ(OK, rv);
[email protected]09356c652014-03-25 15:36:101536 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491537}
1538
[email protected]23e482282013-06-14 16:08:021539TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:231540 KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061541 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]202965992011-12-07 23:04:511542 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1543}
1544
[email protected]23e482282013-06-14 16:08:021545TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061546 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]202965992011-12-07 23:04:511547 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251548}
1549
[email protected]23e482282013-06-14 16:08:021550TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061551 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]202965992011-12-07 23:04:511552 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251553}
1554
[email protected]d58ceea82014-06-04 10:55:541555// Make sure that on a 408 response (Request Timeout), the request is retried,
1556// if the socket was a reused keep alive socket.
1557TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1558 MockRead read_failure(SYNCHRONOUS,
1559 "HTTP/1.1 408 Request Timeout\r\n"
1560 "Connection: Keep-Alive\r\n"
1561 "Content-Length: 6\r\n\r\n"
1562 "Pickle");
1563 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1564}
1565
[email protected]a34f61ee2014-03-18 20:59:491566TEST_P(HttpNetworkTransactionTest,
1567 PreconnectErrorNotConnectedOnWrite) {
1568 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]09356c652014-03-25 15:36:101569 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
[email protected]a34f61ee2014-03-18 20:59:491570}
1571
1572TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1573 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]09356c652014-03-25 15:36:101574 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491575}
1576
1577TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1578 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]09356c652014-03-25 15:36:101579 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1580}
1581
1582TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1583 MockRead read_failure(ASYNC, OK); // EOF
1584 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1585}
1586
[email protected]d58ceea82014-06-04 10:55:541587// Make sure that on a 408 response (Request Timeout), the request is retried,
1588// if the socket was a preconnected (UNUSED_IDLE) socket.
1589TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1590 MockRead read_failure(SYNCHRONOUS,
1591 "HTTP/1.1 408 Request Timeout\r\n"
1592 "Connection: Keep-Alive\r\n"
1593 "Content-Length: 6\r\n\r\n"
1594 "Pickle");
1595 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1596 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1597}
1598
[email protected]09356c652014-03-25 15:36:101599TEST_P(HttpNetworkTransactionTest,
1600 SpdyPreconnectErrorNotConnectedOnWrite) {
1601 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1602 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1603}
1604
1605TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1606 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1607 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1608}
1609
1610TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1611 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1612 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1613}
1614
1615TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1616 MockRead read_failure(ASYNC, OK); // EOF
1617 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:491618}
1619
[email protected]23e482282013-06-14 16:08:021620TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421621 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251622 request.method = "GET";
bncce36dca22015-04-21 22:11:231623 request.url = GURL("http://www.example.org/");
[email protected]3d2a59b2008-09-26 19:44:251624 request.load_flags = 0;
1625
mmenkee65e7af2015-10-13 17:16:421626 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271627 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411628 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271629
[email protected]3d2a59b2008-09-26 19:44:251630 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061631 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:351632 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1633 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061634 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251635 };
[email protected]31a2bfe2010-02-09 08:03:391636 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071637 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:251638
[email protected]49639fa2011-12-20 23:22:411639 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:251640
[email protected]49639fa2011-12-20 23:22:411641 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421642 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:251643
1644 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421645 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
ttuttled9dbc652015-09-29 20:00:591646
1647 IPEndPoint endpoint;
1648 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
1649 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:251650}
1651
1652// What do various browsers do when the server closes a non-keepalive
1653// connection without sending any response header or body?
1654//
1655// IE7: error page
1656// Safari 3.1.2 (Windows): error page
1657// Firefox 3.0.1: blank page
1658// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:421659// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1660// Us: error page (EMPTY_RESPONSE)
[email protected]23e482282013-06-14 16:08:021661TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:251662 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061663 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:351664 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1665 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061666 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251667 };
[email protected]31a2bfe2010-02-09 08:03:391668 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1669 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:421670 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:251671}
[email protected]038e9a32008-10-08 22:40:161672
[email protected]1826a402014-01-08 15:40:481673// Test that network access can be deferred and resumed.
1674TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1675 HttpRequestInfo request;
1676 request.method = "GET";
bncce36dca22015-04-21 22:11:231677 request.url = GURL("http://www.example.org/");
[email protected]1826a402014-01-08 15:40:481678 request.load_flags = 0;
1679
mmenkee65e7af2015-10-13 17:16:421680 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1826a402014-01-08 15:40:481681 scoped_ptr<HttpTransaction> trans(
1682 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1683
1684 // Defer on OnBeforeNetworkStart.
1685 BeforeNetworkStartHandler net_start_handler(true); // defer
1686 trans->SetBeforeNetworkStartCallback(
1687 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1688 base::Unretained(&net_start_handler)));
1689
1690 MockRead data_reads[] = {
1691 MockRead("HTTP/1.0 200 OK\r\n"),
1692 MockRead("Content-Length: 5\r\n\r\n"),
1693 MockRead("hello"),
1694 MockRead(SYNCHRONOUS, 0),
1695 };
1696 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1697 session_deps_.socket_factory->AddSocketDataProvider(&data);
1698
1699 TestCompletionCallback callback;
1700
1701 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1702 EXPECT_EQ(ERR_IO_PENDING, rv);
1703 base::MessageLoop::current()->RunUntilIdle();
1704
1705 // Should have deferred for network start.
1706 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1707 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
[email protected]1826a402014-01-08 15:40:481708
1709 trans->ResumeNetworkStart();
1710 rv = callback.WaitForResult();
1711 EXPECT_EQ(OK, rv);
1712 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1713
1714 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1715 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1716 if (rv == ERR_IO_PENDING)
1717 rv = callback.WaitForResult();
1718 EXPECT_EQ(5, rv);
1719 trans.reset();
1720}
1721
1722// Test that network use can be deferred and canceled.
1723TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1724 HttpRequestInfo request;
1725 request.method = "GET";
bncce36dca22015-04-21 22:11:231726 request.url = GURL("http://www.example.org/");
[email protected]1826a402014-01-08 15:40:481727 request.load_flags = 0;
1728
mmenkee65e7af2015-10-13 17:16:421729 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1826a402014-01-08 15:40:481730 scoped_ptr<HttpTransaction> trans(
1731 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1732
1733 // Defer on OnBeforeNetworkStart.
1734 BeforeNetworkStartHandler net_start_handler(true); // defer
1735 trans->SetBeforeNetworkStartCallback(
1736 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1737 base::Unretained(&net_start_handler)));
1738
1739 TestCompletionCallback callback;
1740
1741 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1742 EXPECT_EQ(ERR_IO_PENDING, rv);
1743 base::MessageLoop::current()->RunUntilIdle();
1744
1745 // Should have deferred for network start.
1746 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1747 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
[email protected]1826a402014-01-08 15:40:481748}
1749
[email protected]7a5378b2012-11-04 03:25:171750// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1751// tests. There was a bug causing HttpNetworkTransaction to hang in the
1752// destructor in such situations.
1753// See http://crbug.com/154712 and http://crbug.com/156609.
[email protected]23e482282013-06-14 16:08:021754TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:171755 HttpRequestInfo request;
1756 request.method = "GET";
bncce36dca22015-04-21 22:11:231757 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171758 request.load_flags = 0;
1759
mmenkee65e7af2015-10-13 17:16:421760 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:361761 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501762 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171763
1764 MockRead data_reads[] = {
1765 MockRead("HTTP/1.0 200 OK\r\n"),
1766 MockRead("Connection: keep-alive\r\n"),
1767 MockRead("Content-Length: 100\r\n\r\n"),
1768 MockRead("hello"),
1769 MockRead(SYNCHRONOUS, 0),
1770 };
1771 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071772 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171773
1774 TestCompletionCallback callback;
1775
1776 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1777 EXPECT_EQ(ERR_IO_PENDING, rv);
1778
1779 rv = callback.WaitForResult();
1780 EXPECT_EQ(OK, rv);
1781
1782 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501783 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171784 if (rv == ERR_IO_PENDING)
1785 rv = callback.WaitForResult();
1786 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:501787 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171788 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1789
1790 trans.reset();
[email protected]2da659e2013-05-23 20:51:341791 base::MessageLoop::current()->RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171792 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1793}
1794
[email protected]23e482282013-06-14 16:08:021795TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:171796 HttpRequestInfo request;
1797 request.method = "GET";
bncce36dca22015-04-21 22:11:231798 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171799 request.load_flags = 0;
1800
mmenkee65e7af2015-10-13 17:16:421801 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:361802 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501803 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171804
1805 MockRead data_reads[] = {
1806 MockRead("HTTP/1.0 200 OK\r\n"),
1807 MockRead("Connection: keep-alive\r\n"),
1808 MockRead("Content-Length: 100\r\n\r\n"),
1809 MockRead(SYNCHRONOUS, 0),
1810 };
1811 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071812 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171813
1814 TestCompletionCallback callback;
1815
1816 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1817 EXPECT_EQ(ERR_IO_PENDING, rv);
1818
1819 rv = callback.WaitForResult();
1820 EXPECT_EQ(OK, rv);
1821
1822 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501823 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171824 if (rv == ERR_IO_PENDING)
1825 rv = callback.WaitForResult();
1826 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1827
1828 trans.reset();
[email protected]2da659e2013-05-23 20:51:341829 base::MessageLoop::current()->RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171830 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1831}
1832
[email protected]0b0bf032010-09-21 18:08:501833// Test that we correctly reuse a keep-alive connection after not explicitly
1834// reading the body.
[email protected]23e482282013-06-14 16:08:021835TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:131836 HttpRequestInfo request;
1837 request.method = "GET";
1838 request.url = GURL("http://www.foo.com/");
1839 request.load_flags = 0;
1840
vishal.b62985ca92015-04-17 08:45:511841 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071842 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421843 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271844
mmenkecc2298e2015-12-07 18:20:181845 const char* request_data =
1846 "GET / HTTP/1.1\r\n"
1847 "Host: www.foo.com\r\n"
1848 "Connection: keep-alive\r\n\r\n";
1849 MockWrite data_writes[] = {
1850 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
1851 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
1852 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
1853 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
1854 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
1855 };
1856
[email protected]0b0bf032010-09-21 18:08:501857 // Note that because all these reads happen in the same
1858 // StaticSocketDataProvider, it shows that the same socket is being reused for
1859 // all transactions.
mmenkecc2298e2015-12-07 18:20:181860 MockRead data_reads[] = {
1861 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
1862 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
1863 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
1864 MockRead(ASYNC, 7,
1865 "HTTP/1.1 302 Found\r\n"
1866 "Content-Length: 0\r\n\r\n"),
1867 MockRead(ASYNC, 9,
1868 "HTTP/1.1 302 Found\r\n"
1869 "Content-Length: 5\r\n\r\n"
1870 "hello"),
1871 MockRead(ASYNC, 11,
1872 "HTTP/1.1 301 Moved Permanently\r\n"
1873 "Content-Length: 0\r\n\r\n"),
1874 MockRead(ASYNC, 13,
1875 "HTTP/1.1 301 Moved Permanently\r\n"
1876 "Content-Length: 5\r\n\r\n"
1877 "hello"),
[email protected]fc31d6a42010-06-24 18:05:131878
mmenkecc2298e2015-12-07 18:20:181879 // In the next two rounds, IsConnectedAndIdle returns false, due to
1880 // the set_busy_before_sync_reads(true) call, while the
1881 // HttpNetworkTransaction is being shut down, but the socket is still
1882 // reuseable. See http://crbug.com/544255.
1883 MockRead(ASYNC, 15,
1884 "HTTP/1.1 200 Hunky-Dory\r\n"
1885 "Content-Length: 5\r\n\r\n"),
1886 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:131887
mmenkecc2298e2015-12-07 18:20:181888 MockRead(ASYNC, 18,
1889 "HTTP/1.1 200 Hunky-Dory\r\n"
1890 "Content-Length: 5\r\n\r\n"
1891 "he"),
1892 MockRead(SYNCHRONOUS, 19, "llo"),
1893
1894 // The body of the final request is actually read.
1895 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1896 MockRead(ASYNC, 22, "hello"),
1897 };
1898 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
1899 arraysize(data_writes));
1900 data.set_busy_before_sync_reads(true);
1901 session_deps_.socket_factory->AddSocketDataProvider(&data);
1902
1903 const int kNumUnreadBodies = arraysize(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:501904 std::string response_lines[kNumUnreadBodies];
1905
avibf0746c2015-12-09 19:53:141906 uint32_t first_socket_log_id = NetLog::Source::kInvalidId;
mmenkecc2298e2015-12-07 18:20:181907 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:411908 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:131909
[email protected]262eec82013-03-19 21:01:361910 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501911 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]fc31d6a42010-06-24 18:05:131912
[email protected]49639fa2011-12-20 23:22:411913 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
mmenkecc2298e2015-12-07 18:20:181914 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]fc31d6a42010-06-24 18:05:131915
[email protected]58e32bb2013-01-21 18:23:251916 LoadTimingInfo load_timing_info;
1917 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1918 if (i == 0) {
1919 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1920 first_socket_log_id = load_timing_info.socket_log_id;
1921 } else {
1922 TestLoadTimingReused(load_timing_info);
1923 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1924 }
1925
[email protected]fc31d6a42010-06-24 18:05:131926 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:181927 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:131928
mmenkecc2298e2015-12-07 18:20:181929 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:501930 response_lines[i] = response->headers->GetStatusLine();
1931
mmenkecc2298e2015-12-07 18:20:181932 // Delete the transaction without reading the response bodies. Then spin
1933 // the message loop, so the response bodies are drained.
1934 trans.reset();
1935 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:131936 }
[email protected]0b0bf032010-09-21 18:08:501937
1938 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:181939 "HTTP/1.1 204 No Content",
1940 "HTTP/1.1 205 Reset Content",
1941 "HTTP/1.1 304 Not Modified",
1942 "HTTP/1.1 302 Found",
1943 "HTTP/1.1 302 Found",
1944 "HTTP/1.1 301 Moved Permanently",
1945 "HTTP/1.1 301 Moved Permanently",
1946 "HTTP/1.1 200 Hunky-Dory",
1947 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:501948 };
1949
mostynb91e0da982015-01-20 19:17:271950 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1951 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:501952
1953 for (int i = 0; i < kNumUnreadBodies; ++i)
1954 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1955
[email protected]49639fa2011-12-20 23:22:411956 TestCompletionCallback callback;
[email protected]262eec82013-03-19 21:01:361957 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501958 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:411959 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
mmenkecc2298e2015-12-07 18:20:181960 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]0b0bf032010-09-21 18:08:501961 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:181962 ASSERT_TRUE(response);
1963 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:501964 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1965 std::string response_data;
1966 rv = ReadTransaction(trans.get(), &response_data);
1967 EXPECT_EQ(OK, rv);
1968 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131969}
1970
[email protected]038e9a32008-10-08 22:40:161971// Test the request-challenge-retry sequence for basic auth.
1972// (basic auth is the easiest to mock, because it has no randomness).
[email protected]23e482282013-06-14 16:08:021973TEST_P(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421974 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161975 request.method = "GET";
bncce36dca22015-04-21 22:11:231976 request.url = GURL("http://www.example.org/");
[email protected]038e9a32008-10-08 22:40:161977 request.load_flags = 0;
1978
vishal.b62985ca92015-04-17 08:45:511979 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:071980 session_deps_.net_log = &log;
mmenkee65e7af2015-10-13 17:16:421981 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271982 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411983 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271984
[email protected]f9ee6b52008-11-08 06:46:231985 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:231986 MockWrite(
1987 "GET / HTTP/1.1\r\n"
1988 "Host: www.example.org\r\n"
1989 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:231990 };
1991
[email protected]038e9a32008-10-08 22:40:161992 MockRead data_reads1[] = {
1993 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1994 // Give a couple authenticate options (only the middle one is actually
1995 // supported).
[email protected]22927ad2009-09-21 19:56:191996 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161997 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1998 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1999 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2000 // Large content-length -- won't matter, as connection will be reset.
2001 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062002 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162003 };
2004
2005 // After calling trans->RestartWithAuth(), this is the request we should
2006 // be issuing -- the final header line contains the credentials.
2007 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232008 MockWrite(
2009 "GET / HTTP/1.1\r\n"
2010 "Host: www.example.org\r\n"
2011 "Connection: keep-alive\r\n"
2012 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162013 };
2014
2015 // Lastly, the server responds with the actual content.
2016 MockRead data_reads2[] = {
2017 MockRead("HTTP/1.0 200 OK\r\n"),
2018 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2019 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062020 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162021 };
2022
[email protected]31a2bfe2010-02-09 08:03:392023 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2024 data_writes1, arraysize(data_writes1));
2025 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2026 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:072027 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2028 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162029
[email protected]49639fa2011-12-20 23:22:412030 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162031
[email protected]49639fa2011-12-20 23:22:412032 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422033 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162034
2035 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422036 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162037
[email protected]58e32bb2013-01-21 18:23:252038 LoadTimingInfo load_timing_info1;
2039 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2040 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2041
sclittlefb249892015-09-10 21:33:222042 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2043 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2044 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
[email protected]b8015c42013-12-24 15:18:192045 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2046
[email protected]1c773ea12009-04-28 19:58:422047 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502048 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042049 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162050
[email protected]49639fa2011-12-20 23:22:412051 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162052
[email protected]49639fa2011-12-20 23:22:412053 rv = trans->RestartWithAuth(
2054 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422055 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162056
2057 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422058 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162059
[email protected]58e32bb2013-01-21 18:23:252060 LoadTimingInfo load_timing_info2;
2061 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2062 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2063 // The load timing after restart should have a new socket ID, and times after
2064 // those of the first load timing.
2065 EXPECT_LE(load_timing_info1.receive_headers_end,
2066 load_timing_info2.connect_timing.connect_start);
2067 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2068
sclittlefb249892015-09-10 21:33:222069 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2070 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2071 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
[email protected]b8015c42013-12-24 15:18:192072 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2073
[email protected]038e9a32008-10-08 22:40:162074 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502075 ASSERT_TRUE(response != NULL);
[email protected]038e9a32008-10-08 22:40:162076 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2077 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162078}
2079
ttuttled9dbc652015-09-29 20:00:592080// Test the request-challenge-retry sequence for basic auth.
2081// (basic auth is the easiest to mock, because it has no randomness).
2082TEST_P(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
2083 HttpRequestInfo request;
2084 request.method = "GET";
2085 request.url = GURL("http://www.example.org/");
2086 request.load_flags = 0;
2087
2088 TestNetLog log;
2089 MockHostResolver* resolver = new MockHostResolver();
2090 session_deps_.net_log = &log;
2091 session_deps_.host_resolver.reset(resolver);
mmenkee65e7af2015-10-13 17:16:422092 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
ttuttled9dbc652015-09-29 20:00:592093 scoped_ptr<HttpTransaction> trans(
2094 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2095
2096 resolver->rules()->ClearRules();
2097 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2098
2099 MockWrite data_writes1[] = {
2100 MockWrite("GET / HTTP/1.1\r\n"
2101 "Host: www.example.org\r\n"
2102 "Connection: keep-alive\r\n\r\n"),
2103 };
2104
2105 MockRead data_reads1[] = {
2106 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2107 // Give a couple authenticate options (only the middle one is actually
2108 // supported).
2109 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2110 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2111 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2112 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2113 // Large content-length -- won't matter, as connection will be reset.
2114 MockRead("Content-Length: 10000\r\n\r\n"),
2115 MockRead(SYNCHRONOUS, ERR_FAILED),
2116 };
2117
2118 // After calling trans->RestartWithAuth(), this is the request we should
2119 // be issuing -- the final header line contains the credentials.
2120 MockWrite data_writes2[] = {
2121 MockWrite("GET / HTTP/1.1\r\n"
2122 "Host: www.example.org\r\n"
2123 "Connection: keep-alive\r\n"
2124 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2125 };
2126
2127 // Lastly, the server responds with the actual content.
2128 MockRead data_reads2[] = {
2129 MockRead("HTTP/1.0 200 OK\r\n"),
2130 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2131 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2132 };
2133
2134 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2135 data_writes1, arraysize(data_writes1));
2136 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2137 data_writes2, arraysize(data_writes2));
2138 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2139 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2140
2141 TestCompletionCallback callback1;
2142
2143 EXPECT_EQ(OK, callback1.GetResult(trans->Start(&request, callback1.callback(),
2144 BoundNetLog())));
2145
2146 LoadTimingInfo load_timing_info1;
2147 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2148 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2149
2150 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2151 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2152 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
2153 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2154
2155 const HttpResponseInfo* response = trans->GetResponseInfo();
2156 ASSERT_TRUE(response);
2157 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2158
2159 IPEndPoint endpoint;
2160 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2161 ASSERT_FALSE(endpoint.address().empty());
2162 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2163
2164 resolver->rules()->ClearRules();
2165 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2166
2167 TestCompletionCallback callback2;
2168
2169 EXPECT_EQ(OK, callback2.GetResult(trans->RestartWithAuth(
2170 AuthCredentials(kFoo, kBar), callback2.callback())));
2171
2172 LoadTimingInfo load_timing_info2;
2173 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2174 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2175 // The load timing after restart should have a new socket ID, and times after
2176 // those of the first load timing.
2177 EXPECT_LE(load_timing_info1.receive_headers_end,
2178 load_timing_info2.connect_timing.connect_start);
2179 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2180
2181 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2182 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2183 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
2184 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2185
2186 response = trans->GetResponseInfo();
2187 ASSERT_TRUE(response);
2188 EXPECT_FALSE(response->auth_challenge.get());
2189 EXPECT_EQ(100, response->headers->GetContentLength());
2190
2191 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2192 ASSERT_FALSE(endpoint.address().empty());
2193 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2194}
2195
[email protected]23e482282013-06-14 16:08:022196TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462197 HttpRequestInfo request;
2198 request.method = "GET";
bncce36dca22015-04-21 22:11:232199 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292200 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]861fcd52009-08-26 02:33:462201
mmenkee65e7af2015-10-13 17:16:422202 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272203 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:412204 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:272205
[email protected]861fcd52009-08-26 02:33:462206 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232207 MockWrite(
2208 "GET / HTTP/1.1\r\n"
2209 "Host: www.example.org\r\n"
2210 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462211 };
2212
2213 MockRead data_reads[] = {
2214 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2215 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2216 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2217 // Large content-length -- won't matter, as connection will be reset.
2218 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062219 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462220 };
2221
[email protected]31a2bfe2010-02-09 08:03:392222 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2223 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:072224 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412225 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462226
[email protected]49639fa2011-12-20 23:22:412227 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]861fcd52009-08-26 02:33:462228 EXPECT_EQ(ERR_IO_PENDING, rv);
2229
2230 rv = callback.WaitForResult();
2231 EXPECT_EQ(0, rv);
2232
sclittlefb249892015-09-10 21:33:222233 int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes));
2234 EXPECT_EQ(writes_size, trans->GetTotalSentBytes());
2235 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
[email protected]b8015c42013-12-24 15:18:192236 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2237
[email protected]861fcd52009-08-26 02:33:462238 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502239 ASSERT_TRUE(response != NULL);
[email protected]861fcd52009-08-26 02:33:462240 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2241}
2242
[email protected]2d2697f92009-02-18 21:00:322243// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2244// connection.
[email protected]23e482282013-06-14 16:08:022245TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182246 // On the second pass, the body read of the auth challenge is synchronous, so
2247 // IsConnectedAndIdle returns false. The socket should still be drained and
2248 // reused. See http://crbug.com/544255.
2249 for (int i = 0; i < 2; ++i) {
2250 HttpRequestInfo request;
2251 request.method = "GET";
2252 request.url = GURL("http://www.example.org/");
2253 request.load_flags = 0;
[email protected]2d2697f92009-02-18 21:00:322254
mmenkecc2298e2015-12-07 18:20:182255 TestNetLog log;
2256 session_deps_.net_log = &log;
2257 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272258
mmenkecc2298e2015-12-07 18:20:182259 MockWrite data_writes[] = {
2260 MockWrite(ASYNC, 0,
2261 "GET / HTTP/1.1\r\n"
2262 "Host: www.example.org\r\n"
2263 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322264
mmenkecc2298e2015-12-07 18:20:182265 // After calling trans->RestartWithAuth(), this is the request we should
2266 // be issuing -- the final header line contains the credentials.
2267 MockWrite(ASYNC, 6,
2268 "GET / HTTP/1.1\r\n"
2269 "Host: www.example.org\r\n"
2270 "Connection: keep-alive\r\n"
2271 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2272 };
[email protected]2d2697f92009-02-18 21:00:322273
mmenkecc2298e2015-12-07 18:20:182274 MockRead data_reads[] = {
2275 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2276 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2277 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2278 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2279 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322280
mmenkecc2298e2015-12-07 18:20:182281 // Lastly, the server responds with the actual content.
2282 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2283 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2284 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2285 MockRead(ASYNC, 10, "Hello"),
2286 };
[email protected]2d2697f92009-02-18 21:00:322287
mmenkecc2298e2015-12-07 18:20:182288 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
2289 arraysize(data_writes));
2290 data.set_busy_before_sync_reads(true);
2291 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:462292
mmenkecc2298e2015-12-07 18:20:182293 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322294
mmenkecc2298e2015-12-07 18:20:182295 scoped_ptr<HttpTransaction> trans(
2296 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2297 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2298 ASSERT_EQ(OK, callback1.GetResult(rv));
[email protected]2d2697f92009-02-18 21:00:322299
mmenkecc2298e2015-12-07 18:20:182300 LoadTimingInfo load_timing_info1;
2301 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2302 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:322303
mmenkecc2298e2015-12-07 18:20:182304 const HttpResponseInfo* response = trans->GetResponseInfo();
2305 ASSERT_TRUE(response);
2306 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322307
mmenkecc2298e2015-12-07 18:20:182308 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:252309
mmenkecc2298e2015-12-07 18:20:182310 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
2311 callback2.callback());
2312 ASSERT_EQ(OK, callback2.GetResult(rv));
[email protected]2d2697f92009-02-18 21:00:322313
mmenkecc2298e2015-12-07 18:20:182314 LoadTimingInfo load_timing_info2;
2315 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2316 TestLoadTimingReused(load_timing_info2);
2317 // The load timing after restart should have the same socket ID, and times
2318 // those of the first load timing.
2319 EXPECT_LE(load_timing_info1.receive_headers_end,
2320 load_timing_info2.send_start);
2321 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:322322
mmenkecc2298e2015-12-07 18:20:182323 response = trans->GetResponseInfo();
2324 ASSERT_TRUE(response);
2325 EXPECT_FALSE(response->auth_challenge);
2326 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322327
mmenkecc2298e2015-12-07 18:20:182328 std::string response_data;
2329 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]2d2697f92009-02-18 21:00:322330
mmenkecc2298e2015-12-07 18:20:182331 int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes));
2332 EXPECT_EQ(writes_size, trans->GetTotalSentBytes());
2333 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
2334 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2335 }
[email protected]2d2697f92009-02-18 21:00:322336}
2337
2338// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2339// connection and with no response body to drain.
[email protected]23e482282013-06-14 16:08:022340TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:422341 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322342 request.method = "GET";
bncce36dca22015-04-21 22:11:232343 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322344 request.load_flags = 0;
2345
mmenkee65e7af2015-10-13 17:16:422346 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272347
[email protected]2d2697f92009-02-18 21:00:322348 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232349 MockWrite(
2350 "GET / HTTP/1.1\r\n"
2351 "Host: www.example.org\r\n"
2352 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322353
bncce36dca22015-04-21 22:11:232354 // After calling trans->RestartWithAuth(), this is the request we should
2355 // be issuing -- the final header line contains the credentials.
2356 MockWrite(
2357 "GET / HTTP/1.1\r\n"
2358 "Host: www.example.org\r\n"
2359 "Connection: keep-alive\r\n"
2360 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322361 };
2362
[email protected]2d2697f92009-02-18 21:00:322363 MockRead data_reads1[] = {
2364 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2365 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:312366 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:322367
2368 // Lastly, the server responds with the actual content.
2369 MockRead("HTTP/1.1 200 OK\r\n"),
2370 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502371 MockRead("Content-Length: 5\r\n\r\n"),
2372 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322373 };
2374
[email protected]2d0a4f92011-05-05 16:38:462375 // An incorrect reconnect would cause this to be read.
2376 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062377 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462378 };
2379
[email protected]31a2bfe2010-02-09 08:03:392380 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2381 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462382 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2383 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072384 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2385 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322386
[email protected]49639fa2011-12-20 23:22:412387 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322388
[email protected]262eec82013-03-19 21:01:362389 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502390 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412391 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422392 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322393
2394 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422395 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322396
[email protected]1c773ea12009-04-28 19:58:422397 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502398 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042399 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322400
[email protected]49639fa2011-12-20 23:22:412401 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322402
[email protected]49639fa2011-12-20 23:22:412403 rv = trans->RestartWithAuth(
2404 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422405 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322406
2407 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422408 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322409
2410 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502411 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322412 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502413 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322414}
2415
2416// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2417// connection and with a large response body to drain.
[email protected]23e482282013-06-14 16:08:022418TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:422419 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322420 request.method = "GET";
bncce36dca22015-04-21 22:11:232421 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322422 request.load_flags = 0;
2423
mmenkee65e7af2015-10-13 17:16:422424 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272425
[email protected]2d2697f92009-02-18 21:00:322426 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232427 MockWrite(
2428 "GET / HTTP/1.1\r\n"
2429 "Host: www.example.org\r\n"
2430 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322431
bncce36dca22015-04-21 22:11:232432 // After calling trans->RestartWithAuth(), this is the request we should
2433 // be issuing -- the final header line contains the credentials.
2434 MockWrite(
2435 "GET / HTTP/1.1\r\n"
2436 "Host: www.example.org\r\n"
2437 "Connection: keep-alive\r\n"
2438 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322439 };
2440
2441 // Respond with 5 kb of response body.
2442 std::string large_body_string("Unauthorized");
2443 large_body_string.append(5 * 1024, ' ');
2444 large_body_string.append("\r\n");
2445
2446 MockRead data_reads1[] = {
2447 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2448 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2449 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2450 // 5134 = 12 + 5 * 1024 + 2
2451 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062452 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:322453
2454 // Lastly, the server responds with the actual content.
2455 MockRead("HTTP/1.1 200 OK\r\n"),
2456 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502457 MockRead("Content-Length: 5\r\n\r\n"),
2458 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322459 };
2460
[email protected]2d0a4f92011-05-05 16:38:462461 // An incorrect reconnect would cause this to be read.
2462 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062463 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462464 };
2465
[email protected]31a2bfe2010-02-09 08:03:392466 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2467 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462468 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2469 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072470 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2471 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322472
[email protected]49639fa2011-12-20 23:22:412473 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322474
[email protected]262eec82013-03-19 21:01:362475 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502476 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412477 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422478 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322479
2480 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422481 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322482
[email protected]1c773ea12009-04-28 19:58:422483 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502484 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042485 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322486
[email protected]49639fa2011-12-20 23:22:412487 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322488
[email protected]49639fa2011-12-20 23:22:412489 rv = trans->RestartWithAuth(
2490 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422491 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322492
2493 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422494 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322495
2496 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502497 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322498 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502499 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322500}
2501
2502// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:312503// connection, but the server gets impatient and closes the connection.
[email protected]23e482282013-06-14 16:08:022504TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:312505 HttpRequestInfo request;
2506 request.method = "GET";
bncce36dca22015-04-21 22:11:232507 request.url = GURL("http://www.example.org/");
[email protected]11203f012009-11-12 23:02:312508 request.load_flags = 0;
2509
mmenkee65e7af2015-10-13 17:16:422510 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272511
[email protected]11203f012009-11-12 23:02:312512 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232513 MockWrite(
2514 "GET / HTTP/1.1\r\n"
2515 "Host: www.example.org\r\n"
2516 "Connection: keep-alive\r\n\r\n"),
2517 // This simulates the seemingly successful write to a closed connection
2518 // if the bug is not fixed.
2519 MockWrite(
2520 "GET / HTTP/1.1\r\n"
2521 "Host: www.example.org\r\n"
2522 "Connection: keep-alive\r\n"
2523 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312524 };
2525
2526 MockRead data_reads1[] = {
2527 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2528 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2529 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2530 MockRead("Content-Length: 14\r\n\r\n"),
2531 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:062532 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:312533 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:062534 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:312535 };
2536
2537 // After calling trans->RestartWithAuth(), this is the request we should
2538 // be issuing -- the final header line contains the credentials.
2539 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232540 MockWrite(
2541 "GET / HTTP/1.1\r\n"
2542 "Host: www.example.org\r\n"
2543 "Connection: keep-alive\r\n"
2544 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312545 };
2546
2547 // Lastly, the server responds with the actual content.
2548 MockRead data_reads2[] = {
2549 MockRead("HTTP/1.1 200 OK\r\n"),
2550 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502551 MockRead("Content-Length: 5\r\n\r\n"),
2552 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:312553 };
2554
[email protected]31a2bfe2010-02-09 08:03:392555 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2556 data_writes1, arraysize(data_writes1));
2557 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2558 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:072559 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2560 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:312561
[email protected]49639fa2011-12-20 23:22:412562 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:312563
[email protected]262eec82013-03-19 21:01:362564 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502565 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412566 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]11203f012009-11-12 23:02:312567 EXPECT_EQ(ERR_IO_PENDING, rv);
2568
2569 rv = callback1.WaitForResult();
2570 EXPECT_EQ(OK, rv);
2571
2572 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502573 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042574 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]11203f012009-11-12 23:02:312575
[email protected]49639fa2011-12-20 23:22:412576 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:312577
[email protected]49639fa2011-12-20 23:22:412578 rv = trans->RestartWithAuth(
2579 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]11203f012009-11-12 23:02:312580 EXPECT_EQ(ERR_IO_PENDING, rv);
2581
2582 rv = callback2.WaitForResult();
2583 EXPECT_EQ(OK, rv);
2584
2585 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502586 ASSERT_TRUE(response != NULL);
[email protected]11203f012009-11-12 23:02:312587 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502588 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:312589}
2590
[email protected]394816e92010-08-03 07:38:592591// Test the request-challenge-retry sequence for basic auth, over a connection
2592// that requires a restart when setting up an SSL tunnel.
ttuttle34f63b52015-03-05 04:33:012593TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
2594 HttpRequestInfo request;
2595 request.method = "GET";
bncce36dca22015-04-21 22:11:232596 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:012597 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292598 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:012599
2600 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032601 session_deps_.proxy_service =
2602 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512603 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:012604 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:422605 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:012606
2607 // Since we have proxy, should try to establish tunnel.
2608 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542609 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172610 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542611 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:012612 };
2613
mmenkee71e15332015-10-07 16:39:542614 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:012615 // connection.
2616 MockRead data_reads1[] = {
2617 // No credentials.
2618 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2619 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:542620 };
ttuttle34f63b52015-03-05 04:33:012621
mmenkee71e15332015-10-07 16:39:542622 // Since the first connection couldn't be reused, need to establish another
2623 // once given credentials.
2624 MockWrite data_writes2[] = {
2625 // After calling trans->RestartWithAuth(), this is the request we should
2626 // be issuing -- the final header line contains the credentials.
2627 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172628 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542629 "Proxy-Connection: keep-alive\r\n"
2630 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2631
2632 MockWrite("GET / HTTP/1.1\r\n"
2633 "Host: www.example.org\r\n"
2634 "Connection: keep-alive\r\n\r\n"),
2635 };
2636
2637 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:012638 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2639
2640 MockRead("HTTP/1.1 200 OK\r\n"),
2641 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2642 MockRead("Content-Length: 5\r\n\r\n"),
2643 MockRead(SYNCHRONOUS, "hello"),
2644 };
2645
2646 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2647 data_writes1, arraysize(data_writes1));
2648 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542649 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2650 data_writes2, arraysize(data_writes2));
2651 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:012652 SSLSocketDataProvider ssl(ASYNC, OK);
2653 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2654
2655 TestCompletionCallback callback1;
2656
2657 scoped_ptr<HttpTransaction> trans(
2658 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2659
2660 int rv = trans->Start(&request, callback1.callback(), log.bound());
2661 EXPECT_EQ(ERR_IO_PENDING, rv);
2662
2663 rv = callback1.WaitForResult();
2664 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462665 TestNetLogEntry::List entries;
ttuttle34f63b52015-03-05 04:33:012666 log.GetEntries(&entries);
2667 size_t pos = ExpectLogContainsSomewhere(
2668 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2669 NetLog::PHASE_NONE);
2670 ExpectLogContainsSomewhere(
2671 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2672 NetLog::PHASE_NONE);
2673
2674 const HttpResponseInfo* response = trans->GetResponseInfo();
2675 ASSERT_TRUE(response != NULL);
2676 EXPECT_FALSE(response->headers->IsKeepAlive());
2677 ASSERT_FALSE(response->headers.get() == NULL);
2678 EXPECT_EQ(407, response->headers->response_code());
2679 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2680 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2681
2682 LoadTimingInfo load_timing_info;
2683 // CONNECT requests and responses are handled at the connect job level, so
2684 // the transaction does not yet have a connection.
2685 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2686
2687 TestCompletionCallback callback2;
2688
2689 rv =
2690 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
2691 EXPECT_EQ(ERR_IO_PENDING, rv);
2692
2693 rv = callback2.WaitForResult();
2694 EXPECT_EQ(OK, rv);
2695
2696 response = trans->GetResponseInfo();
2697 ASSERT_TRUE(response != NULL);
2698
2699 EXPECT_TRUE(response->headers->IsKeepAlive());
2700 EXPECT_EQ(200, response->headers->response_code());
2701 EXPECT_EQ(5, response->headers->GetContentLength());
2702 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2703
2704 // The password prompt info should not be set.
2705 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2706
2707 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2708 TestLoadTimingNotReusedWithPac(load_timing_info,
2709 CONNECT_TIMING_HAS_SSL_TIMES);
2710
2711 trans.reset();
2712 session->CloseAllConnections();
2713}
2714
2715// Test the request-challenge-retry sequence for basic auth, over a connection
2716// that requires a restart when setting up an SSL tunnel.
2717TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:592718 HttpRequestInfo request;
2719 request.method = "GET";
bncce36dca22015-04-21 22:11:232720 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:592721 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292722 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]394816e92010-08-03 07:38:592723
[email protected]cb9bf6ca2011-01-28 13:15:272724 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032725 session_deps_.proxy_service =
2726 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512727 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072728 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:422729 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272730
[email protected]394816e92010-08-03 07:38:592731 // Since we have proxy, should try to establish tunnel.
2732 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542733 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172734 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542735 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:112736 };
2737
mmenkee71e15332015-10-07 16:39:542738 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:082739 // connection.
2740 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:542741 // No credentials.
2742 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2743 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2744 MockRead("Proxy-Connection: close\r\n\r\n"),
2745 };
mmenkee0b5c882015-08-26 20:29:112746
mmenkee71e15332015-10-07 16:39:542747 MockWrite data_writes2[] = {
2748 // After calling trans->RestartWithAuth(), this is the request we should
2749 // be issuing -- the final header line contains the credentials.
2750 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172751 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542752 "Proxy-Connection: keep-alive\r\n"
2753 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:082754
mmenkee71e15332015-10-07 16:39:542755 MockWrite("GET / HTTP/1.1\r\n"
2756 "Host: www.example.org\r\n"
2757 "Connection: keep-alive\r\n\r\n"),
2758 };
2759
2760 MockRead data_reads2[] = {
2761 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2762
2763 MockRead("HTTP/1.1 200 OK\r\n"),
2764 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2765 MockRead("Content-Length: 5\r\n\r\n"),
2766 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:592767 };
2768
2769 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2770 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:072771 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542772 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2773 data_writes2, arraysize(data_writes2));
2774 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:062775 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:072776 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:592777
[email protected]49639fa2011-12-20 23:22:412778 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:592779
[email protected]262eec82013-03-19 21:01:362780 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502781 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:502782
[email protected]49639fa2011-12-20 23:22:412783 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]394816e92010-08-03 07:38:592784 EXPECT_EQ(ERR_IO_PENDING, rv);
2785
2786 rv = callback1.WaitForResult();
2787 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462788 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:402789 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:592790 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402791 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:592792 NetLog::PHASE_NONE);
2793 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402794 entries, pos,
[email protected]394816e92010-08-03 07:38:592795 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2796 NetLog::PHASE_NONE);
2797
2798 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502799 ASSERT_TRUE(response != NULL);
ttuttle34f63b52015-03-05 04:33:012800 EXPECT_FALSE(response->headers->IsKeepAlive());
[email protected]90499482013-06-01 00:39:502801 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]394816e92010-08-03 07:38:592802 EXPECT_EQ(407, response->headers->response_code());
2803 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042804 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]394816e92010-08-03 07:38:592805
[email protected]029c83b62013-01-24 05:28:202806 LoadTimingInfo load_timing_info;
2807 // CONNECT requests and responses are handled at the connect job level, so
2808 // the transaction does not yet have a connection.
2809 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2810
[email protected]49639fa2011-12-20 23:22:412811 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:592812
[email protected]49639fa2011-12-20 23:22:412813 rv = trans->RestartWithAuth(
2814 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]394816e92010-08-03 07:38:592815 EXPECT_EQ(ERR_IO_PENDING, rv);
2816
2817 rv = callback2.WaitForResult();
2818 EXPECT_EQ(OK, rv);
2819
2820 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502821 ASSERT_TRUE(response != NULL);
[email protected]394816e92010-08-03 07:38:592822
2823 EXPECT_TRUE(response->headers->IsKeepAlive());
2824 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:502825 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:592826 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2827
2828 // The password prompt info should not be set.
2829 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502830
[email protected]029c83b62013-01-24 05:28:202831 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2832 TestLoadTimingNotReusedWithPac(load_timing_info,
2833 CONNECT_TIMING_HAS_SSL_TIMES);
2834
[email protected]0b0bf032010-09-21 18:08:502835 trans.reset();
[email protected]102e27c2011-02-23 01:01:312836 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:592837}
2838
[email protected]11203f012009-11-12 23:02:312839// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:012840// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2841TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:232842 // On the second pass, the body read of the auth challenge is synchronous, so
2843 // IsConnectedAndIdle returns false. The socket should still be drained and
2844 // reused. See http://crbug.com/544255.
2845 for (int i = 0; i < 2; ++i) {
2846 HttpRequestInfo request;
2847 request.method = "GET";
2848 request.url = GURL("https://www.example.org/");
2849 // Ensure that proxy authentication is attempted even
2850 // when the no authentication data flag is set.
2851 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:012852
mmenked39192ee2015-12-09 00:57:232853 // Configure against proxy server "myproxy:70".
2854 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
2855 BoundTestNetLog log;
2856 session_deps_.net_log = log.bound().net_log();
2857 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:012858
mmenked39192ee2015-12-09 00:57:232859 scoped_ptr<HttpTransaction> trans(
2860 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
ttuttle34f63b52015-03-05 04:33:012861
mmenked39192ee2015-12-09 00:57:232862 // Since we have proxy, should try to establish tunnel.
2863 MockWrite data_writes1[] = {
2864 MockWrite(ASYNC, 0,
2865 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2866 "Host: www.example.org:443\r\n"
2867 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:012868
mmenked39192ee2015-12-09 00:57:232869 // After calling trans->RestartWithAuth(), this is the request we should
2870 // be issuing -- the final header line contains the credentials.
2871 MockWrite(ASYNC, 3,
2872 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2873 "Host: www.example.org:443\r\n"
2874 "Proxy-Connection: keep-alive\r\n"
2875 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2876 };
ttuttle34f63b52015-03-05 04:33:012877
mmenked39192ee2015-12-09 00:57:232878 // The proxy responds to the connect with a 407, using a persistent
2879 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2880 MockRead data_reads1[] = {
2881 // No credentials.
2882 MockRead(ASYNC, 1,
2883 "HTTP/1.0 407 Proxy Authentication Required\r\n"
2884 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
2885 "Proxy-Connection: keep-alive\r\n"
2886 "Content-Length: 10\r\n\r\n"),
2887 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:012888
mmenked39192ee2015-12-09 00:57:232889 // Wrong credentials (wrong password).
2890 MockRead(ASYNC, 4,
2891 "HTTP/1.0 407 Proxy Authentication Required\r\n"
2892 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
2893 "Proxy-Connection: keep-alive\r\n"
2894 "Content-Length: 10\r\n\r\n"),
2895 // No response body because the test stops reading here.
2896 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
2897 };
ttuttle34f63b52015-03-05 04:33:012898
mmenked39192ee2015-12-09 00:57:232899 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
2900 arraysize(data_writes1));
2901 data1.set_busy_before_sync_reads(true);
2902 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:012903
mmenked39192ee2015-12-09 00:57:232904 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:012905
mmenked39192ee2015-12-09 00:57:232906 int rv = trans->Start(&request, callback1.callback(), log.bound());
2907 EXPECT_EQ(OK, callback1.GetResult(rv));
ttuttle34f63b52015-03-05 04:33:012908
mmenked39192ee2015-12-09 00:57:232909 TestNetLogEntry::List entries;
2910 log.GetEntries(&entries);
2911 size_t pos = ExpectLogContainsSomewhere(
2912 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2913 NetLog::PHASE_NONE);
2914 ExpectLogContainsSomewhere(
2915 entries, pos,
2916 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2917 NetLog::PHASE_NONE);
ttuttle34f63b52015-03-05 04:33:012918
mmenked39192ee2015-12-09 00:57:232919 const HttpResponseInfo* response = trans->GetResponseInfo();
2920 ASSERT_TRUE(response);
2921 ASSERT_TRUE(response->headers);
2922 EXPECT_TRUE(response->headers->IsKeepAlive());
2923 EXPECT_EQ(407, response->headers->response_code());
2924 EXPECT_EQ(10, response->headers->GetContentLength());
2925 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2926 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
ttuttle34f63b52015-03-05 04:33:012927
mmenked39192ee2015-12-09 00:57:232928 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:012929
mmenked39192ee2015-12-09 00:57:232930 // Wrong password (should be "bar").
2931 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBaz),
2932 callback2.callback());
2933 EXPECT_EQ(OK, callback2.GetResult(rv));
ttuttle34f63b52015-03-05 04:33:012934
mmenked39192ee2015-12-09 00:57:232935 response = trans->GetResponseInfo();
2936 ASSERT_TRUE(response);
2937 ASSERT_TRUE(response->headers);
2938 EXPECT_TRUE(response->headers->IsKeepAlive());
2939 EXPECT_EQ(407, response->headers->response_code());
2940 EXPECT_EQ(10, response->headers->GetContentLength());
2941 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2942 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
ttuttle34f63b52015-03-05 04:33:012943
mmenked39192ee2015-12-09 00:57:232944 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2945 // out of scope.
2946 session->CloseAllConnections();
2947 }
ttuttle34f63b52015-03-05 04:33:012948}
2949
2950// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2951// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2952TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:232953 // On the second pass, the body read of the auth challenge is synchronous, so
2954 // IsConnectedAndIdle returns false. The socket should still be drained and
2955 // reused. See http://crbug.com/544255.
2956 for (int i = 0; i < 2; ++i) {
2957 HttpRequestInfo request;
2958 request.method = "GET";
2959 request.url = GURL("https://www.example.org/");
2960 // Ensure that proxy authentication is attempted even
2961 // when the no authentication data flag is set.
2962 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2963
2964 // Configure against proxy server "myproxy:70".
2965 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
2966 BoundTestNetLog log;
2967 session_deps_.net_log = log.bound().net_log();
2968 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2969
2970 scoped_ptr<HttpTransaction> trans(
2971 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2972
2973 // Since we have proxy, should try to establish tunnel.
2974 MockWrite data_writes1[] = {
2975 MockWrite(ASYNC, 0,
2976 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2977 "Host: www.example.org:443\r\n"
2978 "Proxy-Connection: keep-alive\r\n\r\n"),
2979
2980 // After calling trans->RestartWithAuth(), this is the request we should
2981 // be issuing -- the final header line contains the credentials.
2982 MockWrite(ASYNC, 3,
2983 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2984 "Host: www.example.org:443\r\n"
2985 "Proxy-Connection: keep-alive\r\n"
2986 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2987 };
2988
2989 // The proxy responds to the connect with a 407, using a persistent
2990 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2991 MockRead data_reads1[] = {
2992 // No credentials.
2993 MockRead(ASYNC, 1,
2994 "HTTP/1.1 407 Proxy Authentication Required\r\n"
2995 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
2996 "Content-Length: 10\r\n\r\n"),
2997 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
2998
2999 // Wrong credentials (wrong password).
3000 MockRead(ASYNC, 4,
3001 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3002 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3003 "Content-Length: 10\r\n\r\n"),
3004 // No response body because the test stops reading here.
3005 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3006 };
3007
3008 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
3009 arraysize(data_writes1));
3010 data1.set_busy_before_sync_reads(true);
3011 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3012
3013 TestCompletionCallback callback1;
3014
3015 int rv = trans->Start(&request, callback1.callback(), log.bound());
3016 EXPECT_EQ(OK, callback1.GetResult(rv));
3017
3018 TestNetLogEntry::List entries;
3019 log.GetEntries(&entries);
3020 size_t pos = ExpectLogContainsSomewhere(
3021 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3022 NetLog::PHASE_NONE);
3023 ExpectLogContainsSomewhere(
3024 entries, pos,
3025 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3026 NetLog::PHASE_NONE);
3027
3028 const HttpResponseInfo* response = trans->GetResponseInfo();
3029 ASSERT_TRUE(response);
3030 ASSERT_TRUE(response->headers);
3031 EXPECT_TRUE(response->headers->IsKeepAlive());
3032 EXPECT_EQ(407, response->headers->response_code());
3033 EXPECT_EQ(10, response->headers->GetContentLength());
3034 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3035 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3036
3037 TestCompletionCallback callback2;
3038
3039 // Wrong password (should be "bar").
3040 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBaz),
3041 callback2.callback());
3042 EXPECT_EQ(OK, callback2.GetResult(rv));
3043
3044 response = trans->GetResponseInfo();
3045 ASSERT_TRUE(response);
3046 ASSERT_TRUE(response->headers);
3047 EXPECT_TRUE(response->headers->IsKeepAlive());
3048 EXPECT_EQ(407, response->headers->response_code());
3049 EXPECT_EQ(10, response->headers->GetContentLength());
3050 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3051 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3052
3053 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3054 // out of scope.
3055 session->CloseAllConnections();
3056 }
3057}
3058
3059// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3060// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3061// the case the server sends extra data on the original socket, so it can't be
3062// reused.
3063TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273064 HttpRequestInfo request;
3065 request.method = "GET";
bncce36dca22015-04-21 22:11:233066 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273067 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293068 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]cb9bf6ca2011-01-28 13:15:273069
[email protected]2d2697f92009-02-18 21:00:323070 // Configure against proxy server "myproxy:70".
mmenked39192ee2015-12-09 00:57:233071 session_deps_.proxy_service =
3072 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:513073 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073074 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423075 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323076
[email protected]2d2697f92009-02-18 21:00:323077 // Since we have proxy, should try to establish tunnel.
3078 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233079 MockWrite(ASYNC, 0,
3080 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173081 "Host: www.example.org:443\r\n"
3082 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233083 };
[email protected]2d2697f92009-02-18 21:00:323084
mmenked39192ee2015-12-09 00:57:233085 // The proxy responds to the connect with a 407, using a persistent, but sends
3086 // extra data, so the socket cannot be reused.
3087 MockRead data_reads1[] = {
3088 // No credentials.
3089 MockRead(ASYNC, 1,
3090 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3091 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3092 "Content-Length: 10\r\n\r\n"),
3093 MockRead(SYNCHRONOUS, 2, "0123456789"),
3094 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3095 };
3096
3097 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233098 // After calling trans->RestartWithAuth(), this is the request we should
3099 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233100 MockWrite(ASYNC, 0,
3101 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173102 "Host: www.example.org:443\r\n"
3103 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233104 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3105
3106 MockWrite(ASYNC, 2,
3107 "GET / HTTP/1.1\r\n"
3108 "Host: www.example.org\r\n"
3109 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323110 };
3111
mmenked39192ee2015-12-09 00:57:233112 MockRead data_reads2[] = {
3113 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323114
mmenked39192ee2015-12-09 00:57:233115 MockRead(ASYNC, 3,
3116 "HTTP/1.1 200 OK\r\n"
3117 "Content-Type: text/html; charset=iso-8859-1\r\n"
3118 "Content-Length: 5\r\n\r\n"),
3119 // No response body because the test stops reading here.
3120 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323121 };
3122
mmenked39192ee2015-12-09 00:57:233123 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
3124 arraysize(data_writes1));
3125 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073126 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenked39192ee2015-12-09 00:57:233127 SequencedSocketData data2(data_reads2, arraysize(data_reads2), data_writes2,
3128 arraysize(data_writes2));
3129 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3130 SSLSocketDataProvider ssl(ASYNC, OK);
3131 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323132
[email protected]49639fa2011-12-20 23:22:413133 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323134
mmenked39192ee2015-12-09 00:57:233135 scoped_ptr<HttpTransaction> trans(
3136 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d2697f92009-02-18 21:00:323137
mmenked39192ee2015-12-09 00:57:233138 int rv = trans->Start(&request, callback1.callback(), log.bound());
3139 EXPECT_EQ(OK, callback1.GetResult(rv));
3140
mmenke43758e62015-05-04 21:09:463141 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403142 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:393143 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403144 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:393145 NetLog::PHASE_NONE);
3146 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403147 entries, pos,
[email protected]dbb83db2010-05-11 18:13:393148 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3149 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:323150
[email protected]1c773ea12009-04-28 19:58:423151 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243152 ASSERT_TRUE(response);
3153 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323154 EXPECT_TRUE(response->headers->IsKeepAlive());
3155 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423156 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:043157 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:323158
mmenked39192ee2015-12-09 00:57:233159 LoadTimingInfo load_timing_info;
3160 // CONNECT requests and responses are handled at the connect job level, so
3161 // the transaction does not yet have a connection.
3162 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3163
[email protected]49639fa2011-12-20 23:22:413164 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323165
mmenked39192ee2015-12-09 00:57:233166 rv =
3167 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
3168 EXPECT_EQ(OK, callback2.GetResult(rv));
[email protected]2d2697f92009-02-18 21:00:323169
[email protected]2d2697f92009-02-18 21:00:323170 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233171 EXPECT_EQ(200, response->headers->response_code());
3172 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423173 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133174
mmenked39192ee2015-12-09 00:57:233175 // The password prompt info should not be set.
3176 EXPECT_FALSE(response->auth_challenge);
3177
3178 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3179 TestLoadTimingNotReusedWithPac(load_timing_info,
3180 CONNECT_TIMING_HAS_SSL_TIMES);
3181
3182 trans.reset();
[email protected]102e27c2011-02-23 01:01:313183 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323184}
3185
mmenkee71e15332015-10-07 16:39:543186// Test the case a proxy closes a socket while the challenge body is being
3187// drained.
3188TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
3189 HttpRequestInfo request;
3190 request.method = "GET";
3191 request.url = GURL("https://www.example.org/");
3192 // Ensure that proxy authentication is attempted even
3193 // when the no authentication data flag is set.
3194 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
3195
3196 // Configure against proxy server "myproxy:70".
3197 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:423198 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543199
3200 scoped_ptr<HttpTransaction> trans(
3201 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3202
3203 // Since we have proxy, should try to establish tunnel.
3204 MockWrite data_writes1[] = {
3205 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173206 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543207 "Proxy-Connection: keep-alive\r\n\r\n"),
3208 };
3209
3210 // The proxy responds to the connect with a 407, using a persistent
3211 // connection.
3212 MockRead data_reads1[] = {
3213 // No credentials.
3214 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3215 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3216 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3217 // Server hands up in the middle of the body.
3218 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3219 };
3220
3221 MockWrite data_writes2[] = {
3222 // After calling trans->RestartWithAuth(), this is the request we should
3223 // be issuing -- the final header line contains the credentials.
3224 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173225 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543226 "Proxy-Connection: keep-alive\r\n"
3227 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3228
3229 MockWrite("GET / HTTP/1.1\r\n"
3230 "Host: www.example.org\r\n"
3231 "Connection: keep-alive\r\n\r\n"),
3232 };
3233
3234 MockRead data_reads2[] = {
3235 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3236
3237 MockRead("HTTP/1.1 200 OK\r\n"),
3238 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3239 MockRead("Content-Length: 5\r\n\r\n"),
3240 MockRead(SYNCHRONOUS, "hello"),
3241 };
3242
3243 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3244 data_writes1, arraysize(data_writes1));
3245 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3246 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3247 data_writes2, arraysize(data_writes2));
3248 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3249 SSLSocketDataProvider ssl(ASYNC, OK);
3250 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3251
3252 TestCompletionCallback callback;
3253
3254 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3255 EXPECT_EQ(OK, callback.GetResult(rv));
3256
3257 const HttpResponseInfo* response = trans->GetResponseInfo();
3258 ASSERT_TRUE(response);
3259 ASSERT_TRUE(response->headers);
3260 EXPECT_TRUE(response->headers->IsKeepAlive());
3261 EXPECT_EQ(407, response->headers->response_code());
3262 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3263
3264 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
3265 EXPECT_EQ(OK, callback.GetResult(rv));
3266
3267 response = trans->GetResponseInfo();
3268 ASSERT_TRUE(response);
3269 ASSERT_TRUE(response->headers);
3270 EXPECT_TRUE(response->headers->IsKeepAlive());
3271 EXPECT_EQ(200, response->headers->response_code());
3272 std::string body;
3273 EXPECT_EQ(OK, ReadTransaction(trans.get(), &body));
3274 EXPECT_EQ("hello", body);
3275}
3276
[email protected]a8e9b162009-03-12 00:06:443277// Test that we don't read the response body when we fail to establish a tunnel,
3278// even if the user cancels the proxy's auth attempt.
[email protected]23e482282013-06-14 16:08:023279TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273280 HttpRequestInfo request;
3281 request.method = "GET";
bncce36dca22015-04-21 22:11:233282 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273283 request.load_flags = 0;
3284
[email protected]a8e9b162009-03-12 00:06:443285 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033286 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]a8e9b162009-03-12 00:06:443287
mmenkee65e7af2015-10-13 17:16:423288 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443289
[email protected]262eec82013-03-19 21:01:363290 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503291 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]a8e9b162009-03-12 00:06:443292
[email protected]a8e9b162009-03-12 00:06:443293 // Since we have proxy, should try to establish tunnel.
3294 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173295 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3296 "Host: www.example.org:443\r\n"
3297 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443298 };
3299
3300 // The proxy responds to the connect with a 407.
3301 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243302 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3303 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3304 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233305 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:243306 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443307 };
3308
[email protected]31a2bfe2010-02-09 08:03:393309 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3310 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:073311 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443312
[email protected]49639fa2011-12-20 23:22:413313 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443314
[email protected]49639fa2011-12-20 23:22:413315 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423316 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:443317
3318 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423319 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:443320
[email protected]1c773ea12009-04-28 19:58:423321 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243322 ASSERT_TRUE(response);
3323 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:443324 EXPECT_TRUE(response->headers->IsKeepAlive());
3325 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423326 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:443327
3328 std::string response_data;
3329 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423330 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:183331
3332 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:313333 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:443334}
3335
ttuttle7933c112015-01-06 00:55:243336// Test that we don't pass extraneous headers from the proxy's response to the
3337// caller when the proxy responds to CONNECT with 407.
3338TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
3339 HttpRequestInfo request;
3340 request.method = "GET";
bncce36dca22015-04-21 22:11:233341 request.url = GURL("https://www.example.org/");
ttuttle7933c112015-01-06 00:55:243342 request.load_flags = 0;
3343
3344 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033345 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
ttuttle7933c112015-01-06 00:55:243346
mmenkee65e7af2015-10-13 17:16:423347 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:243348
3349 scoped_ptr<HttpTransaction> trans(
3350 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3351
3352 // Since we have proxy, should try to establish tunnel.
3353 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173354 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3355 "Host: www.example.org:443\r\n"
3356 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:243357 };
3358
3359 // The proxy responds to the connect with a 407.
3360 MockRead data_reads[] = {
3361 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3362 MockRead("X-Foo: bar\r\n"),
3363 MockRead("Set-Cookie: foo=bar\r\n"),
3364 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3365 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233366 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:243367 };
3368
3369 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
3370 arraysize(data_writes));
3371 session_deps_.socket_factory->AddSocketDataProvider(&data);
3372
3373 TestCompletionCallback callback;
3374
3375 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3376 EXPECT_EQ(ERR_IO_PENDING, rv);
3377
3378 rv = callback.WaitForResult();
3379 EXPECT_EQ(OK, rv);
3380
3381 const HttpResponseInfo* response = trans->GetResponseInfo();
3382 ASSERT_TRUE(response);
3383 ASSERT_TRUE(response->headers);
3384 EXPECT_TRUE(response->headers->IsKeepAlive());
3385 EXPECT_EQ(407, response->headers->response_code());
3386 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3387 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
3388 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
3389
3390 std::string response_data;
3391 rv = ReadTransaction(trans.get(), &response_data);
3392 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3393
3394 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3395 session->CloseAllConnections();
3396}
3397
[email protected]8fdbcd22010-05-05 02:54:523398// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
3399// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
[email protected]23e482282013-06-14 16:08:023400TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:523401 HttpRequestInfo request;
3402 request.method = "GET";
bncce36dca22015-04-21 22:11:233403 request.url = GURL("http://www.example.org/");
[email protected]8fdbcd22010-05-05 02:54:523404 request.load_flags = 0;
3405
[email protected]cb9bf6ca2011-01-28 13:15:273406 // We are using a DIRECT connection (i.e. no proxy) for this session.
mmenkee65e7af2015-10-13 17:16:423407 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273408 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:413409 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:273410
[email protected]8fdbcd22010-05-05 02:54:523411 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233412 MockWrite(
3413 "GET / HTTP/1.1\r\n"
3414 "Host: www.example.org\r\n"
3415 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:523416 };
3417
3418 MockRead data_reads1[] = {
3419 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
3420 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3421 // Large content-length -- won't matter, as connection will be reset.
3422 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063423 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:523424 };
3425
3426 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3427 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073428 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:523429
[email protected]49639fa2011-12-20 23:22:413430 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:523431
[email protected]49639fa2011-12-20 23:22:413432 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]8fdbcd22010-05-05 02:54:523433 EXPECT_EQ(ERR_IO_PENDING, rv);
3434
3435 rv = callback.WaitForResult();
3436 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3437}
3438
[email protected]7a67a8152010-11-05 18:31:103439// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3440// through a non-authenticating proxy. The request should fail with
3441// ERR_UNEXPECTED_PROXY_AUTH.
3442// Note that it is impossible to detect if an HTTP server returns a 407 through
3443// a non-authenticating proxy - there is nothing to indicate whether the
3444// response came from the proxy or the server, so it is treated as if the proxy
3445// issued the challenge.
[email protected]23e482282013-06-14 16:08:023446TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:233447 HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:273448 HttpRequestInfo request;
3449 request.method = "GET";
bncce36dca22015-04-21 22:11:233450 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273451
rdsmith82957ad2015-09-16 19:42:033452 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:513453 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073454 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423455 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:103456
[email protected]7a67a8152010-11-05 18:31:103457 // Since we have proxy, should try to establish tunnel.
3458 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:173459 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3460 "Host: www.example.org:443\r\n"
3461 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103462
rsleevidb16bb02015-11-12 23:47:173463 MockWrite("GET / HTTP/1.1\r\n"
3464 "Host: www.example.org\r\n"
3465 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103466 };
3467
3468 MockRead data_reads1[] = {
3469 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3470
3471 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3472 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3473 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:063474 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:103475 };
3476
3477 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3478 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073479 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:063480 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073481 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:103482
[email protected]49639fa2011-12-20 23:22:413483 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:103484
[email protected]262eec82013-03-19 21:01:363485 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503486 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a67a8152010-11-05 18:31:103487
[email protected]49639fa2011-12-20 23:22:413488 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7a67a8152010-11-05 18:31:103489 EXPECT_EQ(ERR_IO_PENDING, rv);
3490
3491 rv = callback1.WaitForResult();
3492 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
mmenke43758e62015-05-04 21:09:463493 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403494 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:103495 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403496 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:103497 NetLog::PHASE_NONE);
3498 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403499 entries, pos,
[email protected]7a67a8152010-11-05 18:31:103500 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3501 NetLog::PHASE_NONE);
3502}
[email protected]2df19bb2010-08-25 20:13:463503
mmenke2a1781d2015-10-07 19:25:333504// Test a proxy auth scheme that allows default credentials and a proxy server
3505// that uses non-persistent connections.
3506TEST_P(HttpNetworkTransactionTest,
3507 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
3508 HttpRequestInfo request;
3509 request.method = "GET";
3510 request.url = GURL("https://www.example.org/");
3511
3512 // Configure against proxy server "myproxy:70".
3513 session_deps_.proxy_service =
3514 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3515
3516 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3517 new HttpAuthHandlerMock::Factory());
3518 auth_handler_factory->set_do_init_from_challenge(true);
3519 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3520 mock_handler->set_allows_default_credentials(true);
3521 auth_handler_factory->AddMockHandler(mock_handler.release(),
3522 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483523 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333524
3525 // Add NetLog just so can verify load timing information gets a NetLog ID.
3526 NetLog net_log;
3527 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423528 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333529
3530 // Since we have proxy, should try to establish tunnel.
3531 MockWrite data_writes1[] = {
3532 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173533 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333534 "Proxy-Connection: keep-alive\r\n\r\n"),
3535 };
3536
3537 // The proxy responds to the connect with a 407, using a non-persistent
3538 // connection.
3539 MockRead data_reads1[] = {
3540 // No credentials.
3541 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3542 MockRead("Proxy-Authenticate: Mock\r\n"),
3543 MockRead("Proxy-Connection: close\r\n\r\n"),
3544 };
3545
3546 // Since the first connection couldn't be reused, need to establish another
3547 // once given credentials.
3548 MockWrite data_writes2[] = {
3549 // After calling trans->RestartWithAuth(), this is the request we should
3550 // be issuing -- the final header line contains the credentials.
3551 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173552 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333553 "Proxy-Connection: keep-alive\r\n"
3554 "Proxy-Authorization: auth_token\r\n\r\n"),
3555
3556 MockWrite("GET / HTTP/1.1\r\n"
3557 "Host: www.example.org\r\n"
3558 "Connection: keep-alive\r\n\r\n"),
3559 };
3560
3561 MockRead data_reads2[] = {
3562 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3563
3564 MockRead("HTTP/1.1 200 OK\r\n"),
3565 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3566 MockRead("Content-Length: 5\r\n\r\n"),
3567 MockRead(SYNCHRONOUS, "hello"),
3568 };
3569
3570 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3571 data_writes1, arraysize(data_writes1));
3572 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3573 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3574 data_writes2, arraysize(data_writes2));
3575 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3576 SSLSocketDataProvider ssl(ASYNC, OK);
3577 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3578
3579 scoped_ptr<HttpTransaction> trans(
3580 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3581
3582 TestCompletionCallback callback;
3583 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3584 EXPECT_EQ(OK, callback.GetResult(rv));
3585
3586 const HttpResponseInfo* response = trans->GetResponseInfo();
3587 ASSERT_TRUE(response);
3588 ASSERT_TRUE(response->headers);
3589 EXPECT_FALSE(response->headers->IsKeepAlive());
3590 EXPECT_EQ(407, response->headers->response_code());
3591 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3592 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3593 EXPECT_FALSE(response->auth_challenge.get());
3594
3595 LoadTimingInfo load_timing_info;
3596 // CONNECT requests and responses are handled at the connect job level, so
3597 // the transaction does not yet have a connection.
3598 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3599
3600 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3601 EXPECT_EQ(OK, callback.GetResult(rv));
3602 response = trans->GetResponseInfo();
3603 ASSERT_TRUE(response);
3604 ASSERT_TRUE(response->headers);
3605 EXPECT_TRUE(response->headers->IsKeepAlive());
3606 EXPECT_EQ(200, response->headers->response_code());
3607 EXPECT_EQ(5, response->headers->GetContentLength());
3608 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3609
3610 // The password prompt info should not be set.
3611 EXPECT_FALSE(response->auth_challenge);
3612
3613 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3614 TestLoadTimingNotReusedWithPac(load_timing_info,
3615 CONNECT_TIMING_HAS_SSL_TIMES);
3616
3617 trans.reset();
3618 session->CloseAllConnections();
3619}
3620
3621// Test a proxy auth scheme that allows default credentials and a proxy server
3622// that hangs up when credentials are initially sent.
3623TEST_P(HttpNetworkTransactionTest,
3624 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
3625 HttpRequestInfo request;
3626 request.method = "GET";
3627 request.url = GURL("https://www.example.org/");
3628
3629 // Configure against proxy server "myproxy:70".
3630 session_deps_.proxy_service =
3631 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3632
3633 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3634 new HttpAuthHandlerMock::Factory());
3635 auth_handler_factory->set_do_init_from_challenge(true);
3636 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3637 mock_handler->set_allows_default_credentials(true);
3638 auth_handler_factory->AddMockHandler(mock_handler.release(),
3639 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483640 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333641
3642 // Add NetLog just so can verify load timing information gets a NetLog ID.
3643 NetLog net_log;
3644 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423645 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333646
3647 // Should try to establish tunnel.
3648 MockWrite data_writes1[] = {
3649 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173650 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333651 "Proxy-Connection: keep-alive\r\n\r\n"),
3652
3653 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173654 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333655 "Proxy-Connection: keep-alive\r\n"
3656 "Proxy-Authorization: auth_token\r\n\r\n"),
3657 };
3658
3659 // The proxy responds to the connect with a 407, using a non-persistent
3660 // connection.
3661 MockRead data_reads1[] = {
3662 // No credentials.
3663 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3664 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3665 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3666 };
3667
3668 // Since the first connection was closed, need to establish another once given
3669 // credentials.
3670 MockWrite data_writes2[] = {
3671 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173672 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333673 "Proxy-Connection: keep-alive\r\n"
3674 "Proxy-Authorization: auth_token\r\n\r\n"),
3675
3676 MockWrite("GET / HTTP/1.1\r\n"
3677 "Host: www.example.org\r\n"
3678 "Connection: keep-alive\r\n\r\n"),
3679 };
3680
3681 MockRead data_reads2[] = {
3682 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3683
3684 MockRead("HTTP/1.1 200 OK\r\n"),
3685 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3686 MockRead("Content-Length: 5\r\n\r\n"),
3687 MockRead(SYNCHRONOUS, "hello"),
3688 };
3689
3690 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3691 data_writes1, arraysize(data_writes1));
3692 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3693 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3694 data_writes2, arraysize(data_writes2));
3695 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3696 SSLSocketDataProvider ssl(ASYNC, OK);
3697 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3698
3699 scoped_ptr<HttpTransaction> trans(
3700 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3701
3702 TestCompletionCallback callback;
3703 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3704 EXPECT_EQ(OK, callback.GetResult(rv));
3705
3706 const HttpResponseInfo* response = trans->GetResponseInfo();
3707 ASSERT_TRUE(response);
3708 ASSERT_TRUE(response->headers);
3709 EXPECT_TRUE(response->headers->IsKeepAlive());
3710 EXPECT_EQ(407, response->headers->response_code());
3711 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3712 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3713 EXPECT_FALSE(response->auth_challenge);
3714
3715 LoadTimingInfo load_timing_info;
3716 // CONNECT requests and responses are handled at the connect job level, so
3717 // the transaction does not yet have a connection.
3718 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3719
3720 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3721 EXPECT_EQ(OK, callback.GetResult(rv));
3722
3723 response = trans->GetResponseInfo();
3724 ASSERT_TRUE(response);
3725 ASSERT_TRUE(response->headers);
3726 EXPECT_TRUE(response->headers->IsKeepAlive());
3727 EXPECT_EQ(200, response->headers->response_code());
3728 EXPECT_EQ(5, response->headers->GetContentLength());
3729 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3730
3731 // The password prompt info should not be set.
3732 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3733
3734 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3735 TestLoadTimingNotReusedWithPac(load_timing_info,
3736 CONNECT_TIMING_HAS_SSL_TIMES);
3737
3738 trans.reset();
3739 session->CloseAllConnections();
3740}
3741
3742// Test a proxy auth scheme that allows default credentials and a proxy server
3743// that hangs up when credentials are initially sent, and hangs up again when
3744// they are retried.
3745TEST_P(HttpNetworkTransactionTest,
3746 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
3747 HttpRequestInfo request;
3748 request.method = "GET";
3749 request.url = GURL("https://www.example.org/");
3750
3751 // Configure against proxy server "myproxy:70".
3752 session_deps_.proxy_service =
3753 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3754
3755 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3756 new HttpAuthHandlerMock::Factory());
3757 auth_handler_factory->set_do_init_from_challenge(true);
3758 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3759 mock_handler->set_allows_default_credentials(true);
3760 auth_handler_factory->AddMockHandler(mock_handler.release(),
3761 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483762 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333763
3764 // Add NetLog just so can verify load timing information gets a NetLog ID.
3765 NetLog net_log;
3766 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423767 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333768
3769 // Should try to establish tunnel.
3770 MockWrite data_writes1[] = {
3771 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173772 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333773 "Proxy-Connection: keep-alive\r\n\r\n"),
3774
3775 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173776 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333777 "Proxy-Connection: keep-alive\r\n"
3778 "Proxy-Authorization: auth_token\r\n\r\n"),
3779 };
3780
3781 // The proxy responds to the connect with a 407, and then hangs up after the
3782 // second request is sent.
3783 MockRead data_reads1[] = {
3784 // No credentials.
3785 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3786 MockRead("Content-Length: 0\r\n"),
3787 MockRead("Proxy-Connection: keep-alive\r\n"),
3788 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3789 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3790 };
3791
3792 // HttpNetworkTransaction sees a reused connection that was closed with
3793 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
3794 // request.
3795 MockWrite data_writes2[] = {
3796 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173797 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333798 "Proxy-Connection: keep-alive\r\n\r\n"),
3799 };
3800
3801 // The proxy, having had more than enough of us, just hangs up.
3802 MockRead data_reads2[] = {
3803 // No credentials.
3804 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3805 };
3806
3807 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3808 data_writes1, arraysize(data_writes1));
3809 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3810 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3811 data_writes2, arraysize(data_writes2));
3812 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3813
3814 scoped_ptr<HttpTransaction> trans(
3815 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3816
3817 TestCompletionCallback callback;
3818 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3819 EXPECT_EQ(OK, callback.GetResult(rv));
3820
3821 const HttpResponseInfo* response = trans->GetResponseInfo();
3822 ASSERT_TRUE(response);
3823 ASSERT_TRUE(response->headers);
3824 EXPECT_TRUE(response->headers->IsKeepAlive());
3825 EXPECT_EQ(407, response->headers->response_code());
3826 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3827 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3828 EXPECT_FALSE(response->auth_challenge);
3829
3830 LoadTimingInfo load_timing_info;
3831 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3832
3833 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3834 EXPECT_EQ(ERR_EMPTY_RESPONSE, callback.GetResult(rv));
3835
3836 trans.reset();
3837 session->CloseAllConnections();
3838}
3839
3840// Test a proxy auth scheme that allows default credentials and a proxy server
3841// that hangs up when credentials are initially sent, and sends a challenge
3842// again they are retried.
3843TEST_P(HttpNetworkTransactionTest,
3844 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
3845 HttpRequestInfo request;
3846 request.method = "GET";
3847 request.url = GURL("https://www.example.org/");
3848
3849 // Configure against proxy server "myproxy:70".
3850 session_deps_.proxy_service =
3851 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3852
3853 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3854 new HttpAuthHandlerMock::Factory());
3855 auth_handler_factory->set_do_init_from_challenge(true);
3856 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3857 mock_handler->set_allows_default_credentials(true);
3858 auth_handler_factory->AddMockHandler(mock_handler.release(),
3859 HttpAuth::AUTH_PROXY);
3860 // Add another handler for the second challenge. It supports default
3861 // credentials, but they shouldn't be used, since they were already tried.
3862 mock_handler.reset(new HttpAuthHandlerMock());
3863 mock_handler->set_allows_default_credentials(true);
3864 auth_handler_factory->AddMockHandler(mock_handler.release(),
3865 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483866 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333867
3868 // Add NetLog just so can verify load timing information gets a NetLog ID.
3869 NetLog net_log;
3870 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423871 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333872
3873 // Should try to establish tunnel.
3874 MockWrite data_writes1[] = {
3875 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173876 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333877 "Proxy-Connection: keep-alive\r\n\r\n"),
3878 };
3879
3880 // The proxy responds to the connect with a 407, using a non-persistent
3881 // connection.
3882 MockRead data_reads1[] = {
3883 // No credentials.
3884 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3885 MockRead("Proxy-Authenticate: Mock\r\n"),
3886 MockRead("Proxy-Connection: close\r\n\r\n"),
3887 };
3888
3889 // Since the first connection was closed, need to establish another once given
3890 // credentials.
3891 MockWrite data_writes2[] = {
3892 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173893 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333894 "Proxy-Connection: keep-alive\r\n"
3895 "Proxy-Authorization: auth_token\r\n\r\n"),
3896 };
3897
3898 MockRead data_reads2[] = {
3899 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3900 MockRead("Proxy-Authenticate: Mock\r\n"),
3901 MockRead("Proxy-Connection: close\r\n\r\n"),
3902 };
3903
3904 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3905 data_writes1, arraysize(data_writes1));
3906 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3907 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3908 data_writes2, arraysize(data_writes2));
3909 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3910 SSLSocketDataProvider ssl(ASYNC, OK);
3911 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3912
3913 scoped_ptr<HttpTransaction> trans(
3914 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3915
3916 TestCompletionCallback callback;
3917 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3918 EXPECT_EQ(OK, callback.GetResult(rv));
3919
3920 const HttpResponseInfo* response = trans->GetResponseInfo();
3921 ASSERT_TRUE(response);
3922 ASSERT_TRUE(response->headers);
3923 EXPECT_EQ(407, response->headers->response_code());
3924 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3925 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3926 EXPECT_FALSE(response->auth_challenge);
3927
3928 LoadTimingInfo load_timing_info;
3929 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3930
3931 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3932 EXPECT_EQ(OK, callback.GetResult(rv));
3933 response = trans->GetResponseInfo();
3934 ASSERT_TRUE(response);
3935 ASSERT_TRUE(response->headers);
3936 EXPECT_EQ(407, response->headers->response_code());
3937 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3938 EXPECT_TRUE(response->auth_challenge);
3939
3940 trans.reset();
3941 session->CloseAllConnections();
3942}
3943
[email protected]029c83b62013-01-24 05:28:203944// Test the load timing for HTTPS requests with an HTTP proxy.
[email protected]23e482282013-06-14 16:08:023945TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:203946 HttpRequestInfo request1;
3947 request1.method = "GET";
bncce36dca22015-04-21 22:11:233948 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:203949
3950 HttpRequestInfo request2;
3951 request2.method = "GET";
bncce36dca22015-04-21 22:11:233952 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:203953
3954 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033955 session_deps_.proxy_service = ProxyService::CreateFixed("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:513956 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073957 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423958 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:203959
3960 // Since we have proxy, should try to establish tunnel.
3961 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:173962 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3963 "Host: www.example.org:443\r\n"
3964 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203965
rsleevidb16bb02015-11-12 23:47:173966 MockWrite("GET /1 HTTP/1.1\r\n"
3967 "Host: www.example.org\r\n"
3968 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203969
rsleevidb16bb02015-11-12 23:47:173970 MockWrite("GET /2 HTTP/1.1\r\n"
3971 "Host: www.example.org\r\n"
3972 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203973 };
3974
3975 // The proxy responds to the connect with a 407, using a persistent
3976 // connection.
3977 MockRead data_reads1[] = {
3978 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3979
3980 MockRead("HTTP/1.1 200 OK\r\n"),
3981 MockRead("Content-Length: 1\r\n\r\n"),
3982 MockRead(SYNCHRONOUS, "1"),
3983
3984 MockRead("HTTP/1.1 200 OK\r\n"),
3985 MockRead("Content-Length: 2\r\n\r\n"),
3986 MockRead(SYNCHRONOUS, "22"),
3987 };
3988
3989 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3990 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073991 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:203992 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073993 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:203994
3995 TestCompletionCallback callback1;
[email protected]262eec82013-03-19 21:01:363996 scoped_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:503997 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:203998
3999 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
4000 EXPECT_EQ(ERR_IO_PENDING, rv);
4001
4002 rv = callback1.WaitForResult();
4003 EXPECT_EQ(OK, rv);
4004
4005 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
4006 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:504007 ASSERT_TRUE(response1->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204008 EXPECT_EQ(1, response1->headers->GetContentLength());
4009
4010 LoadTimingInfo load_timing_info1;
4011 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
4012 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
4013
4014 trans1.reset();
4015
4016 TestCompletionCallback callback2;
[email protected]262eec82013-03-19 21:01:364017 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504018 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204019
4020 rv = trans2->Start(&request2, callback2.callback(), log.bound());
4021 EXPECT_EQ(ERR_IO_PENDING, rv);
4022
4023 rv = callback2.WaitForResult();
4024 EXPECT_EQ(OK, rv);
4025
4026 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
4027 ASSERT_TRUE(response2 != NULL);
[email protected]90499482013-06-01 00:39:504028 ASSERT_TRUE(response2->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204029 EXPECT_EQ(2, response2->headers->GetContentLength());
4030
4031 LoadTimingInfo load_timing_info2;
4032 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4033 TestLoadTimingReused(load_timing_info2);
4034
4035 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
4036
4037 trans2.reset();
4038 session->CloseAllConnections();
4039}
4040
4041// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
[email protected]23e482282013-06-14 16:08:024042TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:204043 HttpRequestInfo request1;
4044 request1.method = "GET";
bncce36dca22015-04-21 22:11:234045 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:204046
4047 HttpRequestInfo request2;
4048 request2.method = "GET";
bncce36dca22015-04-21 22:11:234049 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:204050
4051 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034052 session_deps_.proxy_service =
4053 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:514054 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074055 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424056 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:204057
4058 // Since we have proxy, should try to establish tunnel.
4059 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174060 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4061 "Host: www.example.org:443\r\n"
4062 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204063
rsleevidb16bb02015-11-12 23:47:174064 MockWrite("GET /1 HTTP/1.1\r\n"
4065 "Host: www.example.org\r\n"
4066 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204067
rsleevidb16bb02015-11-12 23:47:174068 MockWrite("GET /2 HTTP/1.1\r\n"
4069 "Host: www.example.org\r\n"
4070 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204071 };
4072
4073 // The proxy responds to the connect with a 407, using a persistent
4074 // connection.
4075 MockRead data_reads1[] = {
4076 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4077
4078 MockRead("HTTP/1.1 200 OK\r\n"),
4079 MockRead("Content-Length: 1\r\n\r\n"),
4080 MockRead(SYNCHRONOUS, "1"),
4081
4082 MockRead("HTTP/1.1 200 OK\r\n"),
4083 MockRead("Content-Length: 2\r\n\r\n"),
4084 MockRead(SYNCHRONOUS, "22"),
4085 };
4086
4087 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4088 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074089 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:204090 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074091 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:204092
4093 TestCompletionCallback callback1;
[email protected]262eec82013-03-19 21:01:364094 scoped_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:504095 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204096
4097 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
4098 EXPECT_EQ(ERR_IO_PENDING, rv);
4099
4100 rv = callback1.WaitForResult();
4101 EXPECT_EQ(OK, rv);
4102
4103 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
4104 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:504105 ASSERT_TRUE(response1->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204106 EXPECT_EQ(1, response1->headers->GetContentLength());
4107
4108 LoadTimingInfo load_timing_info1;
4109 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
4110 TestLoadTimingNotReusedWithPac(load_timing_info1,
4111 CONNECT_TIMING_HAS_SSL_TIMES);
4112
4113 trans1.reset();
4114
4115 TestCompletionCallback callback2;
[email protected]262eec82013-03-19 21:01:364116 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504117 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204118
4119 rv = trans2->Start(&request2, callback2.callback(), log.bound());
4120 EXPECT_EQ(ERR_IO_PENDING, rv);
4121
4122 rv = callback2.WaitForResult();
4123 EXPECT_EQ(OK, rv);
4124
4125 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
4126 ASSERT_TRUE(response2 != NULL);
[email protected]90499482013-06-01 00:39:504127 ASSERT_TRUE(response2->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204128 EXPECT_EQ(2, response2->headers->GetContentLength());
4129
4130 LoadTimingInfo load_timing_info2;
4131 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4132 TestLoadTimingReusedWithPac(load_timing_info2);
4133
4134 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
4135
4136 trans2.reset();
4137 session->CloseAllConnections();
4138}
4139
[email protected]2df19bb2010-08-25 20:13:464140// Test a simple get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024141TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:274142 HttpRequestInfo request;
4143 request.method = "GET";
bncce36dca22015-04-21 22:11:234144 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274145
[email protected]2df19bb2010-08-25 20:13:464146 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034147 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514148 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074149 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424150 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:464151
[email protected]2df19bb2010-08-25 20:13:464152 // Since we have proxy, should use full url
4153 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234154 MockWrite(
4155 "GET http://www.example.org/ HTTP/1.1\r\n"
4156 "Host: www.example.org\r\n"
4157 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:464158 };
4159
4160 MockRead data_reads1[] = {
4161 MockRead("HTTP/1.1 200 OK\r\n"),
4162 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4163 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064164 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:464165 };
4166
4167 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4168 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074169 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064170 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074171 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:464172
[email protected]49639fa2011-12-20 23:22:414173 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:464174
[email protected]262eec82013-03-19 21:01:364175 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504176 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504177
[email protected]49639fa2011-12-20 23:22:414178 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:464179 EXPECT_EQ(ERR_IO_PENDING, rv);
4180
4181 rv = callback1.WaitForResult();
4182 EXPECT_EQ(OK, rv);
4183
[email protected]58e32bb2013-01-21 18:23:254184 LoadTimingInfo load_timing_info;
4185 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4186 TestLoadTimingNotReused(load_timing_info,
4187 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4188
[email protected]2df19bb2010-08-25 20:13:464189 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504190 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464191
4192 EXPECT_TRUE(response->headers->IsKeepAlive());
4193 EXPECT_EQ(200, response->headers->response_code());
4194 EXPECT_EQ(100, response->headers->GetContentLength());
4195 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4196
4197 // The password prompt info should not be set.
4198 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4199}
4200
[email protected]7642b5ae2010-09-01 20:55:174201// Test a SPDY get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024202TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:274203 HttpRequestInfo request;
4204 request.method = "GET";
bncce36dca22015-04-21 22:11:234205 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274206 request.load_flags = 0;
4207
[email protected]7642b5ae2010-09-01 20:55:174208 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034209 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514210 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074211 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424212 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:174213
bncce36dca22015-04-21 22:11:234214 // fetch http://www.example.org/ via SPDY
[email protected]cdf8f7e72013-05-23 10:56:464215 scoped_ptr<SpdyFrame> req(
4216 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rch8e6c6c42015-05-01 14:05:134217 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]7642b5ae2010-09-01 20:55:174218
[email protected]23e482282013-06-14 16:08:024219 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4220 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:174221 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134222 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:174223 };
4224
rch8e6c6c42015-05-01 14:05:134225 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4226 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074227 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:174228
[email protected]8ddf8322012-02-23 18:08:064229 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384230 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074231 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:174232
[email protected]49639fa2011-12-20 23:22:414233 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:174234
[email protected]262eec82013-03-19 21:01:364235 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504236 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504237
[email protected]49639fa2011-12-20 23:22:414238 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7642b5ae2010-09-01 20:55:174239 EXPECT_EQ(ERR_IO_PENDING, rv);
4240
4241 rv = callback1.WaitForResult();
4242 EXPECT_EQ(OK, rv);
4243
[email protected]58e32bb2013-01-21 18:23:254244 LoadTimingInfo load_timing_info;
4245 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4246 TestLoadTimingNotReused(load_timing_info,
4247 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4248
[email protected]7642b5ae2010-09-01 20:55:174249 const HttpResponseInfo* response = trans->GetResponseInfo();
4250 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504251 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024252 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:174253
4254 std::string response_data;
4255 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]448d4ca52012-03-04 04:12:234256 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:174257}
4258
[email protected]1c173852014-06-19 12:51:504259// Verifies that a session which races and wins against the owning transaction
4260// (completing prior to host resolution), doesn't fail the transaction.
4261// Regression test for crbug.com/334413.
4262TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
4263 HttpRequestInfo request;
4264 request.method = "GET";
bncce36dca22015-04-21 22:11:234265 request.url = GURL("http://www.example.org/");
[email protected]1c173852014-06-19 12:51:504266 request.load_flags = 0;
4267
4268 // Configure SPDY proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034269 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514270 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:504271 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424272 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:504273
bncce36dca22015-04-21 22:11:234274 // Fetch http://www.example.org/ through the SPDY proxy.
[email protected]1c173852014-06-19 12:51:504275 scoped_ptr<SpdyFrame> req(
4276 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rch8e6c6c42015-05-01 14:05:134277 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]1c173852014-06-19 12:51:504278
4279 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4280 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
4281 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134282 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:504283 };
4284
rch8e6c6c42015-05-01 14:05:134285 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4286 arraysize(spdy_writes));
[email protected]1c173852014-06-19 12:51:504287 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4288
4289 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384290 ssl.SetNextProto(GetProtocol());
[email protected]1c173852014-06-19 12:51:504291 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4292
4293 TestCompletionCallback callback1;
4294
4295 scoped_ptr<HttpTransaction> trans(
4296 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4297
4298 // Stall the hostname resolution begun by the transaction.
4299 session_deps_.host_resolver->set_synchronous_mode(false);
4300 session_deps_.host_resolver->set_ondemand_mode(true);
4301
4302 int rv = trans->Start(&request, callback1.callback(), log.bound());
4303 EXPECT_EQ(ERR_IO_PENDING, rv);
4304
4305 // Race a session to the proxy, which completes first.
4306 session_deps_.host_resolver->set_ondemand_mode(false);
4307 SpdySessionKey key(
4308 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
4309 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:424310 CreateSecureSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:504311
4312 // Unstall the resolution begun by the transaction.
4313 session_deps_.host_resolver->set_ondemand_mode(true);
4314 session_deps_.host_resolver->ResolveAllPending();
4315
4316 EXPECT_FALSE(callback1.have_result());
4317 rv = callback1.WaitForResult();
4318 EXPECT_EQ(OK, rv);
4319
4320 const HttpResponseInfo* response = trans->GetResponseInfo();
4321 ASSERT_TRUE(response != NULL);
4322 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024323 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:504324
4325 std::string response_data;
4326 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4327 EXPECT_EQ(kUploadData, response_data);
4328}
4329
[email protected]dc7bd1c52010-11-12 00:01:134330// Test a SPDY get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024331TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:274332 HttpRequestInfo request;
4333 request.method = "GET";
bncce36dca22015-04-21 22:11:234334 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274335 request.load_flags = 0;
4336
[email protected]79cb5c12011-09-12 13:12:044337 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034338 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:514339 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074340 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424341 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:134342
[email protected]dc7bd1c52010-11-12 00:01:134343 // The first request will be a bare GET, the second request will be a
4344 // GET with a Proxy-Authorization header.
[email protected]ff98d7f02012-03-22 21:44:194345 scoped_ptr<SpdyFrame> req_get(
[email protected]cdf8f7e72013-05-23 10:56:464346 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rdsmithebb50aa2015-11-12 03:44:384347 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:134348 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464349 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:134350 };
[email protected]ff98d7f02012-03-22 21:44:194351 scoped_ptr<SpdyFrame> req_get_authorization(
[email protected]cdf8f7e72013-05-23 10:56:464352 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4353 arraysize(kExtraAuthorizationHeaders) / 2,
4354 false,
4355 3,
4356 LOWEST,
4357 false));
[email protected]dc7bd1c52010-11-12 00:01:134358 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134359 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:134360 };
4361
4362 // The first response is a 407 proxy authentication challenge, and the second
4363 // response will be a 200 response since the second request includes a valid
4364 // Authorization header.
4365 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464366 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:134367 };
[email protected]ff98d7f02012-03-22 21:44:194368 scoped_ptr<SpdyFrame> resp_authentication(
[email protected]23e482282013-06-14 16:08:024369 spdy_util_.ConstructSpdySynReplyError(
[email protected]dc7bd1c52010-11-12 00:01:134370 "407 Proxy Authentication Required",
4371 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
4372 1));
[email protected]ff98d7f02012-03-22 21:44:194373 scoped_ptr<SpdyFrame> body_authentication(
[email protected]23e482282013-06-14 16:08:024374 spdy_util_.ConstructSpdyBodyFrame(1, true));
4375 scoped_ptr<SpdyFrame> resp_data(
4376 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4377 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:134378 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134379 CreateMockRead(*resp_authentication, 1),
4380 CreateMockRead(*body_authentication, 2),
4381 CreateMockRead(*resp_data, 4),
4382 CreateMockRead(*body_data, 5),
4383 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:134384 };
4385
rch8e6c6c42015-05-01 14:05:134386 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4387 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074388 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:134389
[email protected]8ddf8322012-02-23 18:08:064390 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384391 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074392 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:134393
[email protected]49639fa2011-12-20 23:22:414394 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:134395
[email protected]262eec82013-03-19 21:01:364396 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504397 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]dc7bd1c52010-11-12 00:01:134398
[email protected]49639fa2011-12-20 23:22:414399 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]dc7bd1c52010-11-12 00:01:134400 EXPECT_EQ(ERR_IO_PENDING, rv);
4401
4402 rv = callback1.WaitForResult();
4403 EXPECT_EQ(OK, rv);
4404
4405 const HttpResponseInfo* const response = trans->GetResponseInfo();
4406
4407 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504408 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]dc7bd1c52010-11-12 00:01:134409 EXPECT_EQ(407, response->headers->response_code());
4410 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:044411 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]dc7bd1c52010-11-12 00:01:134412
[email protected]49639fa2011-12-20 23:22:414413 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:134414
[email protected]49639fa2011-12-20 23:22:414415 rv = trans->RestartWithAuth(
4416 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]dc7bd1c52010-11-12 00:01:134417 EXPECT_EQ(ERR_IO_PENDING, rv);
4418
4419 rv = callback2.WaitForResult();
4420 EXPECT_EQ(OK, rv);
4421
4422 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4423
4424 ASSERT_TRUE(response_restart != NULL);
[email protected]90499482013-06-01 00:39:504425 ASSERT_TRUE(response_restart->headers.get() != NULL);
[email protected]dc7bd1c52010-11-12 00:01:134426 EXPECT_EQ(200, response_restart->headers->response_code());
4427 // The password prompt info should not be set.
4428 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4429}
4430
[email protected]d9da5fe2010-10-13 22:37:164431// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
[email protected]23e482282013-06-14 16:08:024432TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:274433 HttpRequestInfo request;
4434 request.method = "GET";
bncce36dca22015-04-21 22:11:234435 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274436 request.load_flags = 0;
4437
[email protected]d9da5fe2010-10-13 22:37:164438 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034439 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514440 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074441 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424442 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164443
[email protected]262eec82013-03-19 21:01:364444 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504445 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164446
bncce36dca22015-04-21 22:11:234447 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344448 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234449 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
4450 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:164451
bncce36dca22015-04-21 22:11:234452 const char get[] =
4453 "GET / HTTP/1.1\r\n"
4454 "Host: www.example.org\r\n"
4455 "Connection: keep-alive\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:194456 scoped_ptr<SpdyFrame> wrapped_get(
[email protected]23e482282013-06-14 16:08:024457 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
4458 scoped_ptr<SpdyFrame> conn_resp(
4459 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:164460 const char resp[] = "HTTP/1.1 200 OK\r\n"
4461 "Content-Length: 10\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:194462 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:024463 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
[email protected]ff98d7f02012-03-22 21:44:194464 scoped_ptr<SpdyFrame> wrapped_body(
[email protected]23e482282013-06-14 16:08:024465 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
[email protected]ff98d7f02012-03-22 21:44:194466 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204467 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
[email protected]8d2f7012012-02-16 00:08:044468
4469 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134470 CreateMockWrite(*connect, 0),
4471 CreateMockWrite(*wrapped_get, 2),
4472 CreateMockWrite(*window_update, 6),
[email protected]8d2f7012012-02-16 00:08:044473 };
4474
[email protected]d9da5fe2010-10-13 22:37:164475 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134476 CreateMockRead(*conn_resp, 1, ASYNC),
4477 CreateMockRead(*wrapped_get_resp, 3, ASYNC),
4478 CreateMockRead(*wrapped_body, 4, ASYNC),
4479 CreateMockRead(*wrapped_body, 5, ASYNC),
4480 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:164481 };
4482
rch8e6c6c42015-05-01 14:05:134483 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4484 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074485 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164486
[email protected]8ddf8322012-02-23 18:08:064487 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384488 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074489 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064490 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074491 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164492
[email protected]49639fa2011-12-20 23:22:414493 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164494
[email protected]49639fa2011-12-20 23:22:414495 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164496 EXPECT_EQ(ERR_IO_PENDING, rv);
4497
4498 rv = callback1.WaitForResult();
rch8e6c6c42015-05-01 14:05:134499 ASSERT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:164500
[email protected]58e32bb2013-01-21 18:23:254501 LoadTimingInfo load_timing_info;
4502 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4503 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4504
[email protected]d9da5fe2010-10-13 22:37:164505 const HttpResponseInfo* response = trans->GetResponseInfo();
4506 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504507 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]d9da5fe2010-10-13 22:37:164508 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4509
4510 std::string response_data;
4511 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4512 EXPECT_EQ("1234567890", response_data);
4513}
4514
4515// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
[email protected]23e482282013-06-14 16:08:024516TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
rdsmithebb50aa2015-11-12 03:44:384517 SpdyTestUtil spdy_util_wrapped(GetProtocol(), GetDependenciesFromPriority());
4518
[email protected]cb9bf6ca2011-01-28 13:15:274519 HttpRequestInfo request;
4520 request.method = "GET";
bncce36dca22015-04-21 22:11:234521 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274522 request.load_flags = 0;
4523
[email protected]d9da5fe2010-10-13 22:37:164524 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034525 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514526 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074527 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424528 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164529
[email protected]262eec82013-03-19 21:01:364530 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504531 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164532
bncce36dca22015-04-21 22:11:234533 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344534 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234535 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
4536 // fetch https://www.example.org/ via SPDY
4537 const char kMyUrl[] = "https://www.example.org/";
[email protected]cdf8f7e72013-05-23 10:56:464538 scoped_ptr<SpdyFrame> get(
rdsmithebb50aa2015-11-12 03:44:384539 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
[email protected]23e482282013-06-14 16:08:024540 scoped_ptr<SpdyFrame> wrapped_get(
4541 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
4542 scoped_ptr<SpdyFrame> conn_resp(
4543 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4544 scoped_ptr<SpdyFrame> get_resp(
rdsmithebb50aa2015-11-12 03:44:384545 spdy_util_wrapped.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:194546 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:024547 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
rdsmithebb50aa2015-11-12 03:44:384548 scoped_ptr<SpdyFrame> body(spdy_util_wrapped.ConstructSpdyBodyFrame(1, true));
[email protected]23e482282013-06-14 16:08:024549 scoped_ptr<SpdyFrame> wrapped_body(
4550 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
[email protected]ff98d7f02012-03-22 21:44:194551 scoped_ptr<SpdyFrame> window_update_get_resp(
[email protected]c10b20852013-05-15 21:29:204552 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
[email protected]ff98d7f02012-03-22 21:44:194553 scoped_ptr<SpdyFrame> window_update_body(
[email protected]c10b20852013-05-15 21:29:204554 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
[email protected]8d2f7012012-02-16 00:08:044555
4556 MockWrite spdy_writes[] = {
rch32320842015-05-16 15:57:094557 CreateMockWrite(*connect, 0),
4558 CreateMockWrite(*wrapped_get, 2),
4559 CreateMockWrite(*window_update_get_resp, 6),
[email protected]8d2f7012012-02-16 00:08:044560 CreateMockWrite(*window_update_body, 7),
4561 };
4562
[email protected]d9da5fe2010-10-13 22:37:164563 MockRead spdy_reads[] = {
rch32320842015-05-16 15:57:094564 CreateMockRead(*conn_resp, 1, ASYNC),
4565 MockRead(ASYNC, ERR_IO_PENDING, 3),
rch8e6c6c42015-05-01 14:05:134566 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
rch32320842015-05-16 15:57:094567 CreateMockRead(*wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:134568 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:164569 };
4570
rch32320842015-05-16 15:57:094571 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4572 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074573 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164574
[email protected]8ddf8322012-02-23 18:08:064575 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384576 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074577 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064578 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384579 ssl2.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074580 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164581
[email protected]49639fa2011-12-20 23:22:414582 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164583
[email protected]49639fa2011-12-20 23:22:414584 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164585 EXPECT_EQ(ERR_IO_PENDING, rv);
4586
rch32320842015-05-16 15:57:094587 // Allow the SpdyProxyClientSocket's write callback to complete.
4588 base::MessageLoop::current()->RunUntilIdle();
4589 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:594590 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:164591 rv = callback1.WaitForResult();
4592 EXPECT_EQ(OK, rv);
4593
[email protected]58e32bb2013-01-21 18:23:254594 LoadTimingInfo load_timing_info;
4595 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4596 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4597
[email protected]d9da5fe2010-10-13 22:37:164598 const HttpResponseInfo* response = trans->GetResponseInfo();
4599 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504600 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024601 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:164602
4603 std::string response_data;
4604 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]448d4ca52012-03-04 04:12:234605 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:164606}
4607
4608// Test a SPDY CONNECT failure through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024609TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:274610 HttpRequestInfo request;
4611 request.method = "GET";
bncce36dca22015-04-21 22:11:234612 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274613 request.load_flags = 0;
4614
[email protected]d9da5fe2010-10-13 22:37:164615 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034616 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514617 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074618 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424619 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164620
[email protected]262eec82013-03-19 21:01:364621 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504622 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164623
bncce36dca22015-04-21 22:11:234624 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344625 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234626 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:204627 scoped_ptr<SpdyFrame> get(
4628 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:164629
4630 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134631 CreateMockWrite(*connect, 0), CreateMockWrite(*get, 2),
[email protected]d9da5fe2010-10-13 22:37:164632 };
4633
[email protected]23e482282013-06-14 16:08:024634 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
4635 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:164636 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134637 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:164638 };
4639
rch8e6c6c42015-05-01 14:05:134640 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4641 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074642 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164643
[email protected]8ddf8322012-02-23 18:08:064644 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384645 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074646 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064647 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384648 ssl2.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074649 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164650
[email protected]49639fa2011-12-20 23:22:414651 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164652
[email protected]49639fa2011-12-20 23:22:414653 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164654 EXPECT_EQ(ERR_IO_PENDING, rv);
4655
4656 rv = callback1.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:174657 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]d9da5fe2010-10-13 22:37:164658
[email protected]4eddbc732012-08-09 05:40:174659 // TODO(ttuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:164660}
4661
[email protected]f6c63db52013-02-02 00:35:224662// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4663// HTTPS Proxy to different servers.
[email protected]23e482282013-06-14 16:08:024664TEST_P(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:224665 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
4666 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034667 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514668 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074669 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424670 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504671 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224672
4673 HttpRequestInfo request1;
4674 request1.method = "GET";
bncce36dca22015-04-21 22:11:234675 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224676 request1.load_flags = 0;
4677
4678 HttpRequestInfo request2;
4679 request2.method = "GET";
bncce36dca22015-04-21 22:11:234680 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:224681 request2.load_flags = 0;
4682
bncce36dca22015-04-21 22:11:234683 // CONNECT to www.example.org:443 via SPDY.
lgarrona91df87f2014-12-05 00:51:344684 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234685 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]23e482282013-06-14 16:08:024686 scoped_ptr<SpdyFrame> conn_resp1(
4687 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f6c63db52013-02-02 00:35:224688
bncce36dca22015-04-21 22:11:234689 // Fetch https://www.example.org/ via HTTP.
4690 const char get1[] =
4691 "GET / HTTP/1.1\r\n"
4692 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224693 "Connection: keep-alive\r\n\r\n";
4694 scoped_ptr<SpdyFrame> wrapped_get1(
[email protected]23e482282013-06-14 16:08:024695 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
[email protected]f6c63db52013-02-02 00:35:224696 const char resp1[] = "HTTP/1.1 200 OK\r\n"
4697 "Content-Length: 1\r\n\r\n";
4698 scoped_ptr<SpdyFrame> wrapped_get_resp1(
[email protected]23e482282013-06-14 16:08:024699 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
4700 scoped_ptr<SpdyFrame> wrapped_body1(
4701 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
[email protected]f6c63db52013-02-02 00:35:224702 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204703 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
[email protected]f6c63db52013-02-02 00:35:224704
bncce36dca22015-04-21 22:11:234705 // CONNECT to mail.example.org:443 via SPDY.
[email protected]745aa9c2014-06-27 02:21:294706 SpdyHeaderBlock connect2_block;
bnc7ecc1122015-09-28 13:22:494707 spdy_util_.MaybeAddVersionHeader(&connect2_block);
[email protected]745aa9c2014-06-27 02:21:294708 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
rdsmithebb50aa2015-11-12 03:44:384709 if (GetProtocol() == kProtoHTTP2) {
bnc6b996d532015-07-29 10:51:324710 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org:443";
4711 } else {
bnc6b996d532015-07-29 10:51:324712 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org";
bnc7ecc1122015-09-28 13:22:494713 connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443";
bnc6b996d532015-07-29 10:51:324714 }
[email protected]f6c63db52013-02-02 00:35:224715 scoped_ptr<SpdyFrame> connect2(
[email protected]745aa9c2014-06-27 02:21:294716 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
[email protected]601e03f12014-04-06 16:26:394717
[email protected]23e482282013-06-14 16:08:024718 scoped_ptr<SpdyFrame> conn_resp2(
4719 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]f6c63db52013-02-02 00:35:224720
bncce36dca22015-04-21 22:11:234721 // Fetch https://mail.example.org/ via HTTP.
4722 const char get2[] =
4723 "GET / HTTP/1.1\r\n"
4724 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224725 "Connection: keep-alive\r\n\r\n";
4726 scoped_ptr<SpdyFrame> wrapped_get2(
[email protected]23e482282013-06-14 16:08:024727 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
[email protected]f6c63db52013-02-02 00:35:224728 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4729 "Content-Length: 2\r\n\r\n";
4730 scoped_ptr<SpdyFrame> wrapped_get_resp2(
[email protected]23e482282013-06-14 16:08:024731 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
[email protected]f6c63db52013-02-02 00:35:224732 scoped_ptr<SpdyFrame> wrapped_body2(
[email protected]23e482282013-06-14 16:08:024733 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
[email protected]f6c63db52013-02-02 00:35:224734
4735 MockWrite spdy_writes[] = {
4736 CreateMockWrite(*connect1, 0),
4737 CreateMockWrite(*wrapped_get1, 2),
4738 CreateMockWrite(*connect2, 5),
4739 CreateMockWrite(*wrapped_get2, 7),
4740 };
4741
4742 MockRead spdy_reads[] = {
4743 CreateMockRead(*conn_resp1, 1, ASYNC),
4744 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4745 CreateMockRead(*wrapped_body1, 4, ASYNC),
4746 CreateMockRead(*conn_resp2, 6, ASYNC),
4747 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
4748 CreateMockRead(*wrapped_body2, 9, ASYNC),
4749 MockRead(ASYNC, 0, 10),
4750 };
4751
mmenke11eb5152015-06-09 14:50:504752 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4753 arraysize(spdy_writes));
4754 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224755
4756 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384757 ssl.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:504758 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224759 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504760 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:224761 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504762 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:224763
4764 TestCompletionCallback callback;
4765
[email protected]262eec82013-03-19 21:01:364766 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504767 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224768 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504769 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224770
4771 LoadTimingInfo load_timing_info;
4772 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4773 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4774
4775 const HttpResponseInfo* response = trans->GetResponseInfo();
4776 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504777 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]f6c63db52013-02-02 00:35:224778 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4779
4780 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:294781 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
mmenke11eb5152015-06-09 14:50:504782 rv = trans->Read(buf.get(), 256, callback.callback());
4783 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224784
[email protected]262eec82013-03-19 21:01:364785 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504786 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224787 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504788 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224789
4790 LoadTimingInfo load_timing_info2;
4791 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4792 // Even though the SPDY connection is reused, a new tunnelled connection has
4793 // to be created, so the socket's load timing looks like a fresh connection.
4794 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
4795
4796 // The requests should have different IDs, since they each are using their own
4797 // separate stream.
4798 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4799
mmenke11eb5152015-06-09 14:50:504800 rv = trans2->Read(buf.get(), 256, callback.callback());
4801 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224802}
4803
4804// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4805// HTTPS Proxy to the same server.
[email protected]23e482282013-06-14 16:08:024806TEST_P(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:224807 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
4808 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034809 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514810 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074811 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424812 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504813 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224814
4815 HttpRequestInfo request1;
4816 request1.method = "GET";
bncce36dca22015-04-21 22:11:234817 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224818 request1.load_flags = 0;
4819
4820 HttpRequestInfo request2;
4821 request2.method = "GET";
bncce36dca22015-04-21 22:11:234822 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:224823 request2.load_flags = 0;
4824
bncce36dca22015-04-21 22:11:234825 // CONNECT to www.example.org:443 via SPDY.
lgarrona91df87f2014-12-05 00:51:344826 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234827 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]23e482282013-06-14 16:08:024828 scoped_ptr<SpdyFrame> conn_resp1(
4829 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f6c63db52013-02-02 00:35:224830
bncce36dca22015-04-21 22:11:234831 // Fetch https://www.example.org/ via HTTP.
4832 const char get1[] =
4833 "GET / HTTP/1.1\r\n"
4834 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224835 "Connection: keep-alive\r\n\r\n";
4836 scoped_ptr<SpdyFrame> wrapped_get1(
[email protected]23e482282013-06-14 16:08:024837 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
[email protected]f6c63db52013-02-02 00:35:224838 const char resp1[] = "HTTP/1.1 200 OK\r\n"
4839 "Content-Length: 1\r\n\r\n";
4840 scoped_ptr<SpdyFrame> wrapped_get_resp1(
[email protected]23e482282013-06-14 16:08:024841 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
4842 scoped_ptr<SpdyFrame> wrapped_body1(
4843 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
[email protected]f6c63db52013-02-02 00:35:224844 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204845 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
[email protected]f6c63db52013-02-02 00:35:224846
bncce36dca22015-04-21 22:11:234847 // Fetch https://www.example.org/2 via HTTP.
4848 const char get2[] =
4849 "GET /2 HTTP/1.1\r\n"
4850 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224851 "Connection: keep-alive\r\n\r\n";
4852 scoped_ptr<SpdyFrame> wrapped_get2(
[email protected]23e482282013-06-14 16:08:024853 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
[email protected]f6c63db52013-02-02 00:35:224854 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4855 "Content-Length: 2\r\n\r\n";
4856 scoped_ptr<SpdyFrame> wrapped_get_resp2(
[email protected]23e482282013-06-14 16:08:024857 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
[email protected]f6c63db52013-02-02 00:35:224858 scoped_ptr<SpdyFrame> wrapped_body2(
[email protected]23e482282013-06-14 16:08:024859 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
[email protected]f6c63db52013-02-02 00:35:224860
4861 MockWrite spdy_writes[] = {
4862 CreateMockWrite(*connect1, 0),
4863 CreateMockWrite(*wrapped_get1, 2),
4864 CreateMockWrite(*wrapped_get2, 5),
4865 };
4866
4867 MockRead spdy_reads[] = {
4868 CreateMockRead(*conn_resp1, 1, ASYNC),
4869 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4870 CreateMockRead(*wrapped_body1, 4, ASYNC),
4871 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
4872 CreateMockRead(*wrapped_body2, 7, ASYNC),
4873 MockRead(ASYNC, 0, 8),
4874 };
4875
mmenke11eb5152015-06-09 14:50:504876 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4877 arraysize(spdy_writes));
4878 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224879
4880 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384881 ssl.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:504882 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224883 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504884 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:224885
4886 TestCompletionCallback callback;
4887
[email protected]262eec82013-03-19 21:01:364888 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504889 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224890 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4891 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f6c63db52013-02-02 00:35:224892
4893 rv = callback.WaitForResult();
4894 EXPECT_EQ(OK, rv);
4895
4896 LoadTimingInfo load_timing_info;
4897 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4898 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4899
4900 const HttpResponseInfo* response = trans->GetResponseInfo();
4901 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504902 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]f6c63db52013-02-02 00:35:224903 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4904
4905 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:294906 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
[email protected]90499482013-06-01 00:39:504907 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:224908 trans.reset();
4909
[email protected]262eec82013-03-19 21:01:364910 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504911 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224912 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4913 EXPECT_EQ(ERR_IO_PENDING, rv);
4914
[email protected]f6c63db52013-02-02 00:35:224915 rv = callback.WaitForResult();
4916 EXPECT_EQ(OK, rv);
4917
4918 LoadTimingInfo load_timing_info2;
4919 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4920 TestLoadTimingReused(load_timing_info2);
4921
4922 // The requests should have the same ID.
4923 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4924
[email protected]90499482013-06-01 00:39:504925 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:224926}
4927
4928// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4929// Proxy to different servers.
mmenke11eb5152015-06-09 14:50:504930TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:224931 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034932 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514933 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074934 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424935 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504936 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224937
4938 HttpRequestInfo request1;
4939 request1.method = "GET";
bncce36dca22015-04-21 22:11:234940 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224941 request1.load_flags = 0;
4942
4943 HttpRequestInfo request2;
4944 request2.method = "GET";
bncce36dca22015-04-21 22:11:234945 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:224946 request2.load_flags = 0;
4947
bncce36dca22015-04-21 22:11:234948 // http://www.example.org/
[email protected]23e482282013-06-14 16:08:024949 scoped_ptr<SpdyHeaderBlock> headers(
bncce36dca22015-04-21 22:11:234950 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
[email protected]745aa9c2014-06-27 02:21:294951 scoped_ptr<SpdyFrame> get1(
4952 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]23e482282013-06-14 16:08:024953 scoped_ptr<SpdyFrame> get_resp1(
4954 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4955 scoped_ptr<SpdyFrame> body1(
4956 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
rdsmithebb50aa2015-11-12 03:44:384957 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:224958
bncce36dca22015-04-21 22:11:234959 // http://mail.example.org/
[email protected]23e482282013-06-14 16:08:024960 scoped_ptr<SpdyHeaderBlock> headers2(
bncce36dca22015-04-21 22:11:234961 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
[email protected]745aa9c2014-06-27 02:21:294962 scoped_ptr<SpdyFrame> get2(
4963 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
[email protected]23e482282013-06-14 16:08:024964 scoped_ptr<SpdyFrame> get_resp2(
4965 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4966 scoped_ptr<SpdyFrame> body2(
4967 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
[email protected]f6c63db52013-02-02 00:35:224968
4969 MockWrite spdy_writes[] = {
4970 CreateMockWrite(*get1, 0),
4971 CreateMockWrite(*get2, 3),
4972 };
4973
4974 MockRead spdy_reads[] = {
4975 CreateMockRead(*get_resp1, 1, ASYNC),
4976 CreateMockRead(*body1, 2, ASYNC),
4977 CreateMockRead(*get_resp2, 4, ASYNC),
4978 CreateMockRead(*body2, 5, ASYNC),
4979 MockRead(ASYNC, 0, 6),
4980 };
4981
mmenke11eb5152015-06-09 14:50:504982 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4983 arraysize(spdy_writes));
4984 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224985
4986 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384987 ssl.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:504988 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224989
4990 TestCompletionCallback callback;
4991
[email protected]262eec82013-03-19 21:01:364992 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504993 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224994 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504995 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224996
4997 LoadTimingInfo load_timing_info;
4998 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4999 TestLoadTimingNotReused(load_timing_info,
5000 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5001
5002 const HttpResponseInfo* response = trans->GetResponseInfo();
5003 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:505004 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025005 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:225006
5007 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:295008 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
mmenke11eb5152015-06-09 14:50:505009 rv = trans->Read(buf.get(), 256, callback.callback());
5010 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:225011 // Delete the first request, so the second one can reuse the socket.
5012 trans.reset();
5013
[email protected]262eec82013-03-19 21:01:365014 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:505015 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:225016 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:505017 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:225018
5019 LoadTimingInfo load_timing_info2;
5020 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5021 TestLoadTimingReused(load_timing_info2);
5022
5023 // The requests should have the same ID.
5024 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
5025
mmenke11eb5152015-06-09 14:50:505026 rv = trans2->Read(buf.get(), 256, callback.callback());
5027 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:225028}
5029
[email protected]2df19bb2010-08-25 20:13:465030// Test the challenge-response-retry sequence through an HTTPS Proxy
[email protected]23e482282013-06-14 16:08:025031TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:465032 HttpRequestInfo request;
5033 request.method = "GET";
bncce36dca22015-04-21 22:11:235034 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:465035 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:295036 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2df19bb2010-08-25 20:13:465037
[email protected]79cb5c12011-09-12 13:12:045038 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035039 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:515040 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075041 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:425042 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275043
[email protected]2df19bb2010-08-25 20:13:465044 // Since we have proxy, should use full url
5045 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235046 MockWrite(
5047 "GET http://www.example.org/ HTTP/1.1\r\n"
5048 "Host: www.example.org\r\n"
5049 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465050
bncce36dca22015-04-21 22:11:235051 // After calling trans->RestartWithAuth(), this is the request we should
5052 // be issuing -- the final header line contains the credentials.
5053 MockWrite(
5054 "GET http://www.example.org/ HTTP/1.1\r\n"
5055 "Host: www.example.org\r\n"
5056 "Proxy-Connection: keep-alive\r\n"
5057 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465058 };
5059
5060 // The proxy responds to the GET with a 407, using a persistent
5061 // connection.
5062 MockRead data_reads1[] = {
5063 // No credentials.
5064 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5065 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5066 MockRead("Proxy-Connection: keep-alive\r\n"),
5067 MockRead("Content-Length: 0\r\n\r\n"),
5068
5069 MockRead("HTTP/1.1 200 OK\r\n"),
5070 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5071 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065072 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:465073 };
5074
5075 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5076 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:075077 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:065078 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075079 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:465080
[email protected]49639fa2011-12-20 23:22:415081 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:465082
[email protected]262eec82013-03-19 21:01:365083 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505084 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505085
[email protected]49639fa2011-12-20 23:22:415086 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:465087 EXPECT_EQ(ERR_IO_PENDING, rv);
5088
5089 rv = callback1.WaitForResult();
5090 EXPECT_EQ(OK, rv);
5091
[email protected]58e32bb2013-01-21 18:23:255092 LoadTimingInfo load_timing_info;
5093 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5094 TestLoadTimingNotReused(load_timing_info,
5095 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5096
[email protected]2df19bb2010-08-25 20:13:465097 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505098 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:505099 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]2df19bb2010-08-25 20:13:465100 EXPECT_EQ(407, response->headers->response_code());
5101 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:045102 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2df19bb2010-08-25 20:13:465103
[email protected]49639fa2011-12-20 23:22:415104 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:465105
[email protected]49639fa2011-12-20 23:22:415106 rv = trans->RestartWithAuth(
5107 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]2df19bb2010-08-25 20:13:465108 EXPECT_EQ(ERR_IO_PENDING, rv);
5109
5110 rv = callback2.WaitForResult();
5111 EXPECT_EQ(OK, rv);
5112
[email protected]58e32bb2013-01-21 18:23:255113 load_timing_info = LoadTimingInfo();
5114 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5115 // Retrying with HTTP AUTH is considered to be reusing a socket.
5116 TestLoadTimingReused(load_timing_info);
5117
[email protected]2df19bb2010-08-25 20:13:465118 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505119 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:465120
5121 EXPECT_TRUE(response->headers->IsKeepAlive());
5122 EXPECT_EQ(200, response->headers->response_code());
5123 EXPECT_EQ(100, response->headers->GetContentLength());
5124 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5125
5126 // The password prompt info should not be set.
5127 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5128}
5129
[email protected]23e482282013-06-14 16:08:025130void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:085131 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:425132 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:085133 request.method = "GET";
bncce36dca22015-04-21 22:11:235134 request.url = GURL("https://www.example.org/");
[email protected]c744cf22009-02-27 07:28:085135 request.load_flags = 0;
5136
[email protected]cb9bf6ca2011-01-28 13:15:275137 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035138 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:425139 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275140
[email protected]c744cf22009-02-27 07:28:085141 // Since we have proxy, should try to establish tunnel.
5142 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:175143 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5144 "Host: www.example.org:443\r\n"
5145 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:085146 };
5147
5148 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:235149 status, MockRead("Content-Length: 10\r\n\r\n"),
5150 // No response body because the test stops reading here.
5151 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:085152 };
5153
[email protected]31a2bfe2010-02-09 08:03:395154 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5155 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:075156 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:085157
[email protected]49639fa2011-12-20 23:22:415158 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:085159
[email protected]262eec82013-03-19 21:01:365160 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505161 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505162
[email protected]49639fa2011-12-20 23:22:415163 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425164 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:085165
5166 rv = callback.WaitForResult();
5167 EXPECT_EQ(expected_status, rv);
5168}
5169
[email protected]23e482282013-06-14 16:08:025170void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:235171 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:085172 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:425173 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:085174}
5175
[email protected]23e482282013-06-14 16:08:025176TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:085177 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
5178}
5179
[email protected]23e482282013-06-14 16:08:025180TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:085181 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
5182}
5183
[email protected]23e482282013-06-14 16:08:025184TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:085185 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
5186}
5187
[email protected]23e482282013-06-14 16:08:025188TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:085189 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
5190}
5191
[email protected]23e482282013-06-14 16:08:025192TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:085193 ConnectStatusHelper(
5194 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
5195}
5196
[email protected]23e482282013-06-14 16:08:025197TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:085198 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
5199}
5200
[email protected]23e482282013-06-14 16:08:025201TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:085202 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
5203}
5204
[email protected]23e482282013-06-14 16:08:025205TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:085206 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
5207}
5208
[email protected]23e482282013-06-14 16:08:025209TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:085210 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
5211}
5212
[email protected]23e482282013-06-14 16:08:025213TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:085214 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
5215}
5216
[email protected]23e482282013-06-14 16:08:025217TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:085218 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
5219}
5220
[email protected]23e482282013-06-14 16:08:025221TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:085222 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
5223}
5224
[email protected]23e482282013-06-14 16:08:025225TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:085226 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
5227}
5228
[email protected]23e482282013-06-14 16:08:025229TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:085230 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
5231}
5232
[email protected]23e482282013-06-14 16:08:025233TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:085234 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
5235}
5236
[email protected]23e482282013-06-14 16:08:025237TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:085238 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
5239}
5240
[email protected]0a17aab32014-04-24 03:32:375241TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
5242 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
5243}
5244
[email protected]23e482282013-06-14 16:08:025245TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:085246 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
5247}
5248
[email protected]23e482282013-06-14 16:08:025249TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:085250 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
5251}
5252
[email protected]23e482282013-06-14 16:08:025253TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:085254 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
5255}
5256
[email protected]23e482282013-06-14 16:08:025257TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:085258 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
5259}
5260
[email protected]23e482282013-06-14 16:08:025261TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:085262 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
5263}
5264
[email protected]23e482282013-06-14 16:08:025265TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:085266 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
5267}
5268
[email protected]23e482282013-06-14 16:08:025269TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:085270 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
5271}
5272
[email protected]23e482282013-06-14 16:08:025273TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:085274 ConnectStatusHelperWithExpectedStatus(
5275 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:545276 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:085277}
5278
[email protected]23e482282013-06-14 16:08:025279TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:085280 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
5281}
5282
[email protected]23e482282013-06-14 16:08:025283TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:085284 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
5285}
5286
[email protected]23e482282013-06-14 16:08:025287TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:085288 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
5289}
5290
[email protected]23e482282013-06-14 16:08:025291TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:085292 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
5293}
5294
[email protected]23e482282013-06-14 16:08:025295TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:085296 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
5297}
5298
[email protected]23e482282013-06-14 16:08:025299TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:085300 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
5301}
5302
[email protected]23e482282013-06-14 16:08:025303TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:085304 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
5305}
5306
[email protected]23e482282013-06-14 16:08:025307TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:085308 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
5309}
5310
[email protected]23e482282013-06-14 16:08:025311TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:085312 ConnectStatusHelper(
5313 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
5314}
5315
[email protected]23e482282013-06-14 16:08:025316TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:085317 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
5318}
5319
[email protected]23e482282013-06-14 16:08:025320TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:085321 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
5322}
5323
[email protected]23e482282013-06-14 16:08:025324TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:085325 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
5326}
5327
[email protected]23e482282013-06-14 16:08:025328TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:085329 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
5330}
5331
[email protected]23e482282013-06-14 16:08:025332TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:085333 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
5334}
5335
[email protected]23e482282013-06-14 16:08:025336TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:085337 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
5338}
5339
[email protected]23e482282013-06-14 16:08:025340TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:085341 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
5342}
5343
[email protected]038e9a32008-10-08 22:40:165344// Test the flow when both the proxy server AND origin server require
5345// authentication. Again, this uses basic auth for both since that is
5346// the simplest to mock.
[email protected]23e482282013-06-14 16:08:025347TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:275348 HttpRequestInfo request;
5349 request.method = "GET";
bncce36dca22015-04-21 22:11:235350 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:275351 request.load_flags = 0;
5352
[email protected]038e9a32008-10-08 22:40:165353 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035354 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:425355 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:075356
5357 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:415358 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]038e9a32008-10-08 22:40:165359
[email protected]f9ee6b52008-11-08 06:46:235360 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235361 MockWrite(
5362 "GET http://www.example.org/ HTTP/1.1\r\n"
5363 "Host: www.example.org\r\n"
5364 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:235365 };
5366
[email protected]038e9a32008-10-08 22:40:165367 MockRead data_reads1[] = {
5368 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
5369 // Give a couple authenticate options (only the middle one is actually
5370 // supported).
[email protected]22927ad2009-09-21 19:56:195371 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:165372 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5373 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
5374 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5375 // Large content-length -- won't matter, as connection will be reset.
5376 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065377 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:165378 };
5379
5380 // After calling trans->RestartWithAuth() the first time, this is the
5381 // request we should be issuing -- the final header line contains the
5382 // proxy's credentials.
5383 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:235384 MockWrite(
5385 "GET http://www.example.org/ HTTP/1.1\r\n"
5386 "Host: www.example.org\r\n"
5387 "Proxy-Connection: keep-alive\r\n"
5388 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:165389 };
5390
5391 // Now the proxy server lets the request pass through to origin server.
5392 // The origin server responds with a 401.
5393 MockRead data_reads2[] = {
5394 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5395 // Note: We are using the same realm-name as the proxy server. This is
5396 // completely valid, as realms are unique across hosts.
5397 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5398 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5399 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065400 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:165401 };
5402
5403 // After calling trans->RestartWithAuth() the second time, we should send
5404 // the credentials for both the proxy and origin server.
5405 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:235406 MockWrite(
5407 "GET http://www.example.org/ HTTP/1.1\r\n"
5408 "Host: www.example.org\r\n"
5409 "Proxy-Connection: keep-alive\r\n"
5410 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
5411 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:165412 };
5413
5414 // Lastly we get the desired content.
5415 MockRead data_reads3[] = {
5416 MockRead("HTTP/1.0 200 OK\r\n"),
5417 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5418 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065419 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:165420 };
5421
[email protected]31a2bfe2010-02-09 08:03:395422 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5423 data_writes1, arraysize(data_writes1));
5424 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5425 data_writes2, arraysize(data_writes2));
5426 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5427 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:075428 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5429 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5430 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:165431
[email protected]49639fa2011-12-20 23:22:415432 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:165433
[email protected]49639fa2011-12-20 23:22:415434 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425435 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165436
5437 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425438 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165439
[email protected]1c773ea12009-04-28 19:58:425440 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505441 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045442 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:165443
[email protected]49639fa2011-12-20 23:22:415444 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:165445
[email protected]49639fa2011-12-20 23:22:415446 rv = trans->RestartWithAuth(
5447 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:425448 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165449
5450 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425451 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165452
5453 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505454 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045455 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:165456
[email protected]49639fa2011-12-20 23:22:415457 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:165458
[email protected]49639fa2011-12-20 23:22:415459 rv = trans->RestartWithAuth(
5460 AuthCredentials(kFoo2, kBar2), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425461 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165462
5463 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425464 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165465
5466 response = trans->GetResponseInfo();
5467 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5468 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:165469}
[email protected]4ddaf2502008-10-23 18:26:195470
[email protected]ea9dc9a2009-09-05 00:43:325471// For the NTLM implementation using SSPI, we skip the NTLM tests since we
5472// can't hook into its internals to cause it to generate predictable NTLM
5473// authorization headers.
5474#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:295475// The NTLM authentication unit tests were generated by capturing the HTTP
5476// requests and responses using Fiddler 2 and inspecting the generated random
5477// bytes in the debugger.
5478
5479// Enter the correct password and authenticate successfully.
[email protected]23e482282013-06-14 16:08:025480TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:425481 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:245482 request.method = "GET";
5483 request.url = GURL("http://172.22.68.17/kids/login.aspx");
[email protected]2217aa22013-10-11 03:03:545484
5485 // Ensure load is not disrupted by flags which suppress behaviour specific
5486 // to other auth schemes.
5487 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:245488
[email protected]cb9bf6ca2011-01-28 13:15:275489 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
5490 MockGetHostName);
mmenkee65e7af2015-10-13 17:16:425491 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275492
[email protected]3f918782009-02-28 01:29:245493 MockWrite data_writes1[] = {
5494 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5495 "Host: 172.22.68.17\r\n"
5496 "Connection: keep-alive\r\n\r\n"),
5497 };
5498
5499 MockRead data_reads1[] = {
5500 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:045501 // Negotiate and NTLM are often requested together. However, we only want
5502 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
5503 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:245504 MockRead("WWW-Authenticate: NTLM\r\n"),
5505 MockRead("Connection: close\r\n"),
5506 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365507 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245508 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065509 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:245510 };
5511
5512 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:225513 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:245514 // request we should be issuing -- the final header line contains a Type
5515 // 1 message.
5516 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5517 "Host: 172.22.68.17\r\n"
5518 "Connection: keep-alive\r\n"
5519 "Authorization: NTLM "
5520 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5521
5522 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5523 // (the credentials for the origin server). The second request continues
5524 // on the same connection.
5525 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5526 "Host: 172.22.68.17\r\n"
5527 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:295528 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5529 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5530 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
5531 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
5532 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245533 };
5534
5535 MockRead data_reads2[] = {
5536 // The origin server responds with a Type 2 message.
5537 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5538 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:295539 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:245540 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5541 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5542 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5543 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5544 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5545 "BtAAAAAAA=\r\n"),
5546 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365547 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245548 MockRead("You are not authorized to view this page\r\n"),
5549
5550 // Lastly we get the desired content.
5551 MockRead("HTTP/1.1 200 OK\r\n"),
5552 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
5553 MockRead("Content-Length: 13\r\n\r\n"),
5554 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:065555 MockRead(SYNCHRONOUS, OK),
[email protected]3f918782009-02-28 01:29:245556 };
5557
[email protected]31a2bfe2010-02-09 08:03:395558 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5559 data_writes1, arraysize(data_writes1));
5560 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5561 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:075562 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5563 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:245564
[email protected]49639fa2011-12-20 23:22:415565 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:245566
[email protected]262eec82013-03-19 21:01:365567 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505568 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505569
[email protected]49639fa2011-12-20 23:22:415570 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425571 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:245572
5573 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425574 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:245575
[email protected]0757e7702009-03-27 04:00:225576 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5577
[email protected]1c773ea12009-04-28 19:58:425578 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:045579 ASSERT_FALSE(response == NULL);
5580 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]3f918782009-02-28 01:29:245581
[email protected]49639fa2011-12-20 23:22:415582 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:255583
[email protected]f3cf9802011-10-28 18:44:585584 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:415585 callback2.callback());
[email protected]10af5fe72011-01-31 16:17:255586 EXPECT_EQ(ERR_IO_PENDING, rv);
5587
5588 rv = callback2.WaitForResult();
5589 EXPECT_EQ(OK, rv);
5590
5591 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5592
5593 response = trans->GetResponseInfo();
5594 ASSERT_TRUE(response != NULL);
[email protected]10af5fe72011-01-31 16:17:255595 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5596
[email protected]49639fa2011-12-20 23:22:415597 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:245598
[email protected]49639fa2011-12-20 23:22:415599 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425600 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:245601
[email protected]0757e7702009-03-27 04:00:225602 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425603 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:245604
5605 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505606 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:245607 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5608 EXPECT_EQ(13, response->headers->GetContentLength());
5609}
5610
[email protected]385a4672009-03-11 22:21:295611// Enter a wrong password, and then the correct one.
[email protected]23e482282013-06-14 16:08:025612TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:425613 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:295614 request.method = "GET";
5615 request.url = GURL("http://172.22.68.17/kids/login.aspx");
5616 request.load_flags = 0;
5617
[email protected]cb9bf6ca2011-01-28 13:15:275618 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
5619 MockGetHostName);
mmenkee65e7af2015-10-13 17:16:425620 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275621
[email protected]385a4672009-03-11 22:21:295622 MockWrite data_writes1[] = {
5623 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5624 "Host: 172.22.68.17\r\n"
5625 "Connection: keep-alive\r\n\r\n"),
5626 };
5627
5628 MockRead data_reads1[] = {
5629 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:045630 // Negotiate and NTLM are often requested together. However, we only want
5631 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
5632 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:295633 MockRead("WWW-Authenticate: NTLM\r\n"),
5634 MockRead("Connection: close\r\n"),
5635 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365636 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295637 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065638 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:295639 };
5640
5641 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:225642 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:295643 // request we should be issuing -- the final header line contains a Type
5644 // 1 message.
5645 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5646 "Host: 172.22.68.17\r\n"
5647 "Connection: keep-alive\r\n"
5648 "Authorization: NTLM "
5649 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5650
5651 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5652 // (the credentials for the origin server). The second request continues
5653 // on the same connection.
5654 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5655 "Host: 172.22.68.17\r\n"
5656 "Connection: keep-alive\r\n"
5657 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5658 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5659 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
5660 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
5661 "4Ww7b7E=\r\n\r\n"),
5662 };
5663
5664 MockRead data_reads2[] = {
5665 // The origin server responds with a Type 2 message.
5666 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5667 MockRead("WWW-Authenticate: NTLM "
5668 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
5669 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5670 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5671 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5672 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5673 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5674 "BtAAAAAAA=\r\n"),
5675 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365676 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295677 MockRead("You are not authorized to view this page\r\n"),
5678
5679 // Wrong password.
5680 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:295681 MockRead("WWW-Authenticate: NTLM\r\n"),
5682 MockRead("Connection: close\r\n"),
5683 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365684 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295685 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065686 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:295687 };
5688
5689 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:225690 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:295691 // request we should be issuing -- the final header line contains a Type
5692 // 1 message.
5693 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5694 "Host: 172.22.68.17\r\n"
5695 "Connection: keep-alive\r\n"
5696 "Authorization: NTLM "
5697 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5698
5699 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5700 // (the credentials for the origin server). The second request continues
5701 // on the same connection.
5702 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5703 "Host: 172.22.68.17\r\n"
5704 "Connection: keep-alive\r\n"
5705 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5706 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5707 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
5708 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
5709 "+4MUm7c=\r\n\r\n"),
5710 };
5711
5712 MockRead data_reads3[] = {
5713 // The origin server responds with a Type 2 message.
5714 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5715 MockRead("WWW-Authenticate: NTLM "
5716 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
5717 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5718 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5719 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5720 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5721 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5722 "BtAAAAAAA=\r\n"),
5723 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365724 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295725 MockRead("You are not authorized to view this page\r\n"),
5726
5727 // Lastly we get the desired content.
5728 MockRead("HTTP/1.1 200 OK\r\n"),
5729 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
5730 MockRead("Content-Length: 13\r\n\r\n"),
5731 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:065732 MockRead(SYNCHRONOUS, OK),
[email protected]385a4672009-03-11 22:21:295733 };
5734
[email protected]31a2bfe2010-02-09 08:03:395735 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5736 data_writes1, arraysize(data_writes1));
5737 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5738 data_writes2, arraysize(data_writes2));
5739 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5740 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:075741 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5742 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5743 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:295744
[email protected]49639fa2011-12-20 23:22:415745 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:295746
[email protected]262eec82013-03-19 21:01:365747 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505748 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505749
[email protected]49639fa2011-12-20 23:22:415750 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425751 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:295752
5753 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425754 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:295755
[email protected]0757e7702009-03-27 04:00:225756 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:295757
[email protected]1c773ea12009-04-28 19:58:425758 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505759 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045760 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]385a4672009-03-11 22:21:295761
[email protected]49639fa2011-12-20 23:22:415762 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:295763
[email protected]0757e7702009-03-27 04:00:225764 // Enter the wrong password.
[email protected]f3cf9802011-10-28 18:44:585765 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
[email protected]49639fa2011-12-20 23:22:415766 callback2.callback());
[email protected]1c773ea12009-04-28 19:58:425767 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:295768
[email protected]10af5fe72011-01-31 16:17:255769 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425770 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:295771
[email protected]0757e7702009-03-27 04:00:225772 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:415773 TestCompletionCallback callback3;
5774 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425775 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:255776 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425777 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:225778 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5779
5780 response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:045781 ASSERT_FALSE(response == NULL);
5782 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]0757e7702009-03-27 04:00:225783
[email protected]49639fa2011-12-20 23:22:415784 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:225785
5786 // Now enter the right password.
[email protected]f3cf9802011-10-28 18:44:585787 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:415788 callback4.callback());
[email protected]10af5fe72011-01-31 16:17:255789 EXPECT_EQ(ERR_IO_PENDING, rv);
5790
5791 rv = callback4.WaitForResult();
5792 EXPECT_EQ(OK, rv);
5793
5794 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5795
[email protected]49639fa2011-12-20 23:22:415796 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:255797
5798 // One more roundtrip
[email protected]49639fa2011-12-20 23:22:415799 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
[email protected]1c773ea12009-04-28 19:58:425800 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:225801
5802 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425803 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:225804
[email protected]385a4672009-03-11 22:21:295805 response = trans->GetResponseInfo();
5806 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5807 EXPECT_EQ(13, response->headers->GetContentLength());
5808}
[email protected]ea9dc9a2009-09-05 00:43:325809#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:295810
[email protected]4ddaf2502008-10-23 18:26:195811// Test reading a server response which has only headers, and no body.
5812// After some maximum number of bytes is consumed, the transaction should
5813// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
[email protected]23e482282013-06-14 16:08:025814TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:425815 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:195816 request.method = "GET";
bncce36dca22015-04-21 22:11:235817 request.url = GURL("http://www.example.org/");
[email protected]4ddaf2502008-10-23 18:26:195818 request.load_flags = 0;
5819
mmenkee65e7af2015-10-13 17:16:425820 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275821 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:415822 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:275823
[email protected]b75b7b2f2009-10-06 00:54:535824 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:435825 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:535826 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:195827
5828 MockRead data_reads[] = {
5829 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:065830 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:195831 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:065832 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:195833 };
[email protected]31a2bfe2010-02-09 08:03:395834 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:075835 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:195836
[email protected]49639fa2011-12-20 23:22:415837 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:195838
[email protected]49639fa2011-12-20 23:22:415839 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425840 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:195841
5842 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425843 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:195844}
[email protected]f4e426b2008-11-05 00:24:495845
5846// Make sure that we don't try to reuse a TCPClientSocket when failing to
5847// establish tunnel.
5848// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]23e482282013-06-14 16:08:025849TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:235850 DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:275851 HttpRequestInfo request;
5852 request.method = "GET";
bncce36dca22015-04-21 22:11:235853 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:275854 request.load_flags = 0;
5855
[email protected]f4e426b2008-11-05 00:24:495856 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035857 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]db8f44c2008-12-13 04:52:015858
mmenkee65e7af2015-10-13 17:16:425859 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:495860
[email protected]262eec82013-03-19 21:01:365861 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505862 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f4e426b2008-11-05 00:24:495863
[email protected]f4e426b2008-11-05 00:24:495864 // Since we have proxy, should try to establish tunnel.
5865 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175866 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5867 "Host: www.example.org:443\r\n"
5868 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:495869 };
5870
[email protected]77848d12008-11-14 00:00:225871 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:495872 // connection. Usually a proxy would return 501 (not implemented),
5873 // or 200 (tunnel established).
5874 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:235875 MockRead("HTTP/1.1 404 Not Found\r\n"),
5876 MockRead("Content-Length: 10\r\n\r\n"),
5877 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:495878 };
5879
[email protected]31a2bfe2010-02-09 08:03:395880 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5881 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:075882 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:495883
[email protected]49639fa2011-12-20 23:22:415884 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:495885
[email protected]49639fa2011-12-20 23:22:415886 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425887 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:495888
5889 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425890 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:495891
[email protected]b4404c02009-04-10 16:38:525892 // Empty the current queue. This is necessary because idle sockets are
5893 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345894 base::MessageLoop::current()->RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:525895
[email protected]f4e426b2008-11-05 00:24:495896 // We now check to make sure the TCPClientSocket was not added back to
5897 // the pool.
[email protected]90499482013-06-01 00:39:505898 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:495899 trans.reset();
[email protected]2da659e2013-05-23 20:51:345900 base::MessageLoop::current()->RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:495901 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:505902 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:495903}
[email protected]372d34a2008-11-05 21:30:515904
[email protected]1b157c02009-04-21 01:55:405905// Make sure that we recycle a socket after reading all of the response body.
[email protected]23e482282013-06-14 16:08:025906TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:425907 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:405908 request.method = "GET";
bncce36dca22015-04-21 22:11:235909 request.url = GURL("http://www.example.org/");
[email protected]1b157c02009-04-21 01:55:405910 request.load_flags = 0;
5911
mmenkee65e7af2015-10-13 17:16:425912 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275913
[email protected]262eec82013-03-19 21:01:365914 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505915 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:275916
[email protected]1b157c02009-04-21 01:55:405917 MockRead data_reads[] = {
5918 // A part of the response body is received with the response headers.
5919 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5920 // The rest of the response body is received in two parts.
5921 MockRead("lo"),
5922 MockRead(" world"),
5923 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:065924 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:405925 };
5926
[email protected]31a2bfe2010-02-09 08:03:395927 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:075928 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:405929
[email protected]49639fa2011-12-20 23:22:415930 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:405931
[email protected]49639fa2011-12-20 23:22:415932 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425933 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:405934
5935 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425936 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:405937
[email protected]1c773ea12009-04-28 19:58:425938 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505939 ASSERT_TRUE(response != NULL);
[email protected]1b157c02009-04-21 01:55:405940
[email protected]90499482013-06-01 00:39:505941 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]1b157c02009-04-21 01:55:405942 std::string status_line = response->headers->GetStatusLine();
5943 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
5944
[email protected]90499482013-06-01 00:39:505945 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:405946
5947 std::string response_data;
5948 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:425949 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:405950 EXPECT_EQ("hello world", response_data);
5951
5952 // Empty the current queue. This is necessary because idle sockets are
5953 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345954 base::MessageLoop::current()->RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:405955
5956 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:505957 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:405958}
5959
[email protected]76a505b2010-08-25 06:23:005960// Make sure that we recycle a SSL socket after reading all of the response
5961// body.
[email protected]23e482282013-06-14 16:08:025962TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:005963 HttpRequestInfo request;
5964 request.method = "GET";
bncce36dca22015-04-21 22:11:235965 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:005966 request.load_flags = 0;
5967
5968 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:235969 MockWrite(
5970 "GET / HTTP/1.1\r\n"
5971 "Host: www.example.org\r\n"
5972 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:005973 };
5974
5975 MockRead data_reads[] = {
5976 MockRead("HTTP/1.1 200 OK\r\n"),
5977 MockRead("Content-Length: 11\r\n\r\n"),
5978 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:065979 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:005980 };
5981
[email protected]8ddf8322012-02-23 18:08:065982 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075983 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:005984
5985 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5986 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:075987 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:005988
[email protected]49639fa2011-12-20 23:22:415989 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:005990
mmenkee65e7af2015-10-13 17:16:425991 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:365992 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505993 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:005994
[email protected]49639fa2011-12-20 23:22:415995 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:005996
5997 EXPECT_EQ(ERR_IO_PENDING, rv);
5998 EXPECT_EQ(OK, callback.WaitForResult());
5999
6000 const HttpResponseInfo* response = trans->GetResponseInfo();
6001 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:506002 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:006003 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6004
[email protected]90499482013-06-01 00:39:506005 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006006
6007 std::string response_data;
6008 rv = ReadTransaction(trans.get(), &response_data);
6009 EXPECT_EQ(OK, rv);
6010 EXPECT_EQ("hello world", response_data);
6011
6012 // Empty the current queue. This is necessary because idle sockets are
6013 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:346014 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:006015
6016 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506017 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006018}
6019
6020// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
6021// from the pool and make sure that we recover okay.
[email protected]23e482282013-06-14 16:08:026022TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:006023 HttpRequestInfo request;
6024 request.method = "GET";
bncce36dca22015-04-21 22:11:236025 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:006026 request.load_flags = 0;
6027
6028 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:236029 MockWrite(
6030 "GET / HTTP/1.1\r\n"
6031 "Host: www.example.org\r\n"
6032 "Connection: keep-alive\r\n\r\n"),
6033 MockWrite(
6034 "GET / HTTP/1.1\r\n"
6035 "Host: www.example.org\r\n"
6036 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:006037 };
6038
6039 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:426040 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
6041 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:006042
[email protected]8ddf8322012-02-23 18:08:066043 SSLSocketDataProvider ssl(ASYNC, OK);
6044 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076045 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6046 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:006047
6048 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6049 data_writes, arraysize(data_writes));
6050 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
6051 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:076052 session_deps_.socket_factory->AddSocketDataProvider(&data);
6053 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:006054
[email protected]49639fa2011-12-20 23:22:416055 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:006056
mmenkee65e7af2015-10-13 17:16:426057 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:366058 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506059 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:006060
[email protected]49639fa2011-12-20 23:22:416061 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:006062
6063 EXPECT_EQ(ERR_IO_PENDING, rv);
6064 EXPECT_EQ(OK, callback.WaitForResult());
6065
6066 const HttpResponseInfo* response = trans->GetResponseInfo();
6067 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:506068 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:006069 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6070
[email protected]90499482013-06-01 00:39:506071 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006072
6073 std::string response_data;
6074 rv = ReadTransaction(trans.get(), &response_data);
6075 EXPECT_EQ(OK, rv);
6076 EXPECT_EQ("hello world", response_data);
6077
6078 // Empty the current queue. This is necessary because idle sockets are
6079 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:346080 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:006081
6082 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506083 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006084
6085 // Now start the second transaction, which should reuse the previous socket.
6086
[email protected]90499482013-06-01 00:39:506087 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:006088
[email protected]49639fa2011-12-20 23:22:416089 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:006090
6091 EXPECT_EQ(ERR_IO_PENDING, rv);
6092 EXPECT_EQ(OK, callback.WaitForResult());
6093
6094 response = trans->GetResponseInfo();
6095 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:506096 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:006097 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6098
[email protected]90499482013-06-01 00:39:506099 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006100
6101 rv = ReadTransaction(trans.get(), &response_data);
6102 EXPECT_EQ(OK, rv);
6103 EXPECT_EQ("hello world", response_data);
6104
6105 // Empty the current queue. This is necessary because idle sockets are
6106 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:346107 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:006108
6109 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506110 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006111}
6112
[email protected]b4404c02009-04-10 16:38:526113// Make sure that we recycle a socket after a zero-length response.
6114// http://crbug.com/9880
[email protected]23e482282013-06-14 16:08:026115TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:426116 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:526117 request.method = "GET";
bncce36dca22015-04-21 22:11:236118 request.url = GURL(
6119 "http://www.example.org/csi?v=3&s=web&action=&"
6120 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
6121 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
6122 "rt=prt.2642,ol.2649,xjs.2951");
[email protected]b4404c02009-04-10 16:38:526123 request.load_flags = 0;
6124
mmenkee65e7af2015-10-13 17:16:426125 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276126
[email protected]b4404c02009-04-10 16:38:526127 MockRead data_reads[] = {
6128 MockRead("HTTP/1.1 204 No Content\r\n"
6129 "Content-Length: 0\r\n"
6130 "Content-Type: text/html\r\n\r\n"),
6131 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:066132 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:526133 };
6134
[email protected]31a2bfe2010-02-09 08:03:396135 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:076136 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:526137
mmenkecc2298e2015-12-07 18:20:186138 // Transaction must be created after the MockReads, so it's destroyed before
6139 // them.
6140 scoped_ptr<HttpTransaction> trans(
6141 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6142
[email protected]49639fa2011-12-20 23:22:416143 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:526144
[email protected]49639fa2011-12-20 23:22:416145 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426146 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:526147
6148 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426149 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:526150
[email protected]1c773ea12009-04-28 19:58:426151 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506152 ASSERT_TRUE(response != NULL);
[email protected]b4404c02009-04-10 16:38:526153
[email protected]90499482013-06-01 00:39:506154 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]b4404c02009-04-10 16:38:526155 std::string status_line = response->headers->GetStatusLine();
6156 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
6157
[email protected]90499482013-06-01 00:39:506158 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:526159
6160 std::string response_data;
6161 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:426162 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:526163 EXPECT_EQ("", response_data);
6164
6165 // Empty the current queue. This is necessary because idle sockets are
6166 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:346167 base::MessageLoop::current()->RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:526168
6169 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506170 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:526171}
6172
[email protected]23e482282013-06-14 16:08:026173TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
olli.raula6df48b2a2015-11-26 07:40:226174 std::vector<scoped_ptr<UploadElementReader>> element_readers;
6175 element_readers.push_back(
6176 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
6177 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:276178
[email protected]1c773ea12009-04-28 19:58:426179 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:516180 // Transaction 1: a GET request that succeeds. The socket is recycled
6181 // after use.
6182 request[0].method = "GET";
6183 request[0].url = GURL("http://www.google.com/");
6184 request[0].load_flags = 0;
6185 // Transaction 2: a POST request. Reuses the socket kept alive from
6186 // transaction 1. The first attempts fails when writing the POST data.
6187 // This causes the transaction to retry with a new socket. The second
6188 // attempt succeeds.
6189 request[1].method = "POST";
6190 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:276191 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:516192 request[1].load_flags = 0;
6193
mmenkee65e7af2015-10-13 17:16:426194 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:516195
6196 // The first socket is used for transaction 1 and the first attempt of
6197 // transaction 2.
6198
6199 // The response of transaction 1.
6200 MockRead data_reads1[] = {
6201 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
6202 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066203 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:516204 };
6205 // The mock write results of transaction 1 and the first attempt of
6206 // transaction 2.
6207 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:066208 MockWrite(SYNCHRONOUS, 64), // GET
6209 MockWrite(SYNCHRONOUS, 93), // POST
6210 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:516211 };
[email protected]31a2bfe2010-02-09 08:03:396212 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6213 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:516214
6215 // The second socket is used for the second attempt of transaction 2.
6216
6217 // The response of transaction 2.
6218 MockRead data_reads2[] = {
6219 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
6220 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:066221 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:516222 };
6223 // The mock write results of the second attempt of transaction 2.
6224 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:066225 MockWrite(SYNCHRONOUS, 93), // POST
6226 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:516227 };
[email protected]31a2bfe2010-02-09 08:03:396228 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6229 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:516230
[email protected]bb88e1d32013-05-03 23:11:076231 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6232 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:516233
thestig9d3bb0c2015-01-24 00:49:516234 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:516235 "hello world", "welcome"
6236 };
6237
6238 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:426239 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506240 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]372d34a2008-11-05 21:30:516241
[email protected]49639fa2011-12-20 23:22:416242 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:516243
[email protected]49639fa2011-12-20 23:22:416244 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426245 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:516246
6247 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426248 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:516249
[email protected]1c773ea12009-04-28 19:58:426250 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506251 ASSERT_TRUE(response != NULL);
[email protected]372d34a2008-11-05 21:30:516252
[email protected]90499482013-06-01 00:39:506253 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]372d34a2008-11-05 21:30:516254 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6255
6256 std::string response_data;
6257 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:426258 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:516259 EXPECT_EQ(kExpectedResponseData[i], response_data);
6260 }
6261}
[email protected]f9ee6b52008-11-08 06:46:236262
6263// Test the request-challenge-retry sequence for basic auth when there is
6264// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:166265// it fails the identity from the URL is used to answer the challenge.
[email protected]23e482282013-06-14 16:08:026266TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:426267 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236268 request.method = "GET";
bncce36dca22015-04-21 22:11:236269 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:416270 request.load_flags = LOAD_NORMAL;
[email protected]a97cca42009-08-14 01:00:296271
mmenkee65e7af2015-10-13 17:16:426272 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276273 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416274 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276275
[email protected]a97cca42009-08-14 01:00:296276 // The password contains an escaped character -- for this test to pass it
6277 // will need to be unescaped by HttpNetworkTransaction.
6278 EXPECT_EQ("b%40r", request.url.password());
6279
[email protected]f9ee6b52008-11-08 06:46:236280 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236281 MockWrite(
6282 "GET / HTTP/1.1\r\n"
6283 "Host: www.example.org\r\n"
6284 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236285 };
6286
6287 MockRead data_reads1[] = {
6288 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6289 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6290 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066291 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236292 };
6293
[email protected]2262e3a2012-05-22 16:08:166294 // After the challenge above, the transaction will be restarted using the
6295 // identity from the url (foo, b@r) to answer the challenge.
6296 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236297 MockWrite(
6298 "GET / HTTP/1.1\r\n"
6299 "Host: www.example.org\r\n"
6300 "Connection: keep-alive\r\n"
6301 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166302 };
6303
6304 MockRead data_reads2[] = {
6305 MockRead("HTTP/1.0 200 OK\r\n"),
6306 MockRead("Content-Length: 100\r\n\r\n"),
6307 MockRead(SYNCHRONOUS, OK),
6308 };
6309
[email protected]31a2bfe2010-02-09 08:03:396310 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6311 data_writes1, arraysize(data_writes1));
[email protected]2262e3a2012-05-22 16:08:166312 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6313 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076314 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6315 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236316
[email protected]49639fa2011-12-20 23:22:416317 TestCompletionCallback callback1;
[email protected]49639fa2011-12-20 23:22:416318 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426319 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236320 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426321 EXPECT_EQ(OK, rv);
[email protected]2262e3a2012-05-22 16:08:166322 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6323
6324 TestCompletionCallback callback2;
6325 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6326 EXPECT_EQ(ERR_IO_PENDING, rv);
6327 rv = callback2.WaitForResult();
6328 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226329 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6330
[email protected]2262e3a2012-05-22 16:08:166331 const HttpResponseInfo* response = trans->GetResponseInfo();
6332 ASSERT_TRUE(response != NULL);
6333
6334 // There is no challenge info, since the identity in URL worked.
6335 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6336
6337 EXPECT_EQ(100, response->headers->GetContentLength());
6338
6339 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:346340 base::MessageLoop::current()->RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:166341}
6342
6343// Test the request-challenge-retry sequence for basic auth when there is an
6344// incorrect identity in the URL. The identity from the URL should be used only
6345// once.
[email protected]23e482282013-06-14 16:08:026346TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:166347 HttpRequestInfo request;
6348 request.method = "GET";
6349 // Note: the URL has a username:password in it. The password "baz" is
6350 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:236351 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:166352
6353 request.load_flags = LOAD_NORMAL;
6354
mmenkee65e7af2015-10-13 17:16:426355 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2262e3a2012-05-22 16:08:166356 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416357 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2262e3a2012-05-22 16:08:166358
6359 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236360 MockWrite(
6361 "GET / HTTP/1.1\r\n"
6362 "Host: www.example.org\r\n"
6363 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166364 };
6365
6366 MockRead data_reads1[] = {
6367 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6368 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6369 MockRead("Content-Length: 10\r\n\r\n"),
6370 MockRead(SYNCHRONOUS, ERR_FAILED),
6371 };
6372
6373 // After the challenge above, the transaction will be restarted using the
6374 // identity from the url (foo, baz) to answer the challenge.
6375 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236376 MockWrite(
6377 "GET / HTTP/1.1\r\n"
6378 "Host: www.example.org\r\n"
6379 "Connection: keep-alive\r\n"
6380 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166381 };
6382
6383 MockRead data_reads2[] = {
6384 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6385 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6386 MockRead("Content-Length: 10\r\n\r\n"),
6387 MockRead(SYNCHRONOUS, ERR_FAILED),
6388 };
6389
6390 // After the challenge above, the transaction will be restarted using the
6391 // identity supplied by the user (foo, bar) to answer the challenge.
6392 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236393 MockWrite(
6394 "GET / HTTP/1.1\r\n"
6395 "Host: www.example.org\r\n"
6396 "Connection: keep-alive\r\n"
6397 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166398 };
6399
6400 MockRead data_reads3[] = {
6401 MockRead("HTTP/1.0 200 OK\r\n"),
6402 MockRead("Content-Length: 100\r\n\r\n"),
6403 MockRead(SYNCHRONOUS, OK),
6404 };
6405
6406 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6407 data_writes1, arraysize(data_writes1));
6408 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6409 data_writes2, arraysize(data_writes2));
6410 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6411 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:076412 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6413 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6414 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:166415
6416 TestCompletionCallback callback1;
6417
6418 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6419 EXPECT_EQ(ERR_IO_PENDING, rv);
6420
6421 rv = callback1.WaitForResult();
6422 EXPECT_EQ(OK, rv);
6423
6424 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6425 TestCompletionCallback callback2;
6426 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6427 EXPECT_EQ(ERR_IO_PENDING, rv);
6428 rv = callback2.WaitForResult();
6429 EXPECT_EQ(OK, rv);
6430 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6431
6432 const HttpResponseInfo* response = trans->GetResponseInfo();
6433 ASSERT_TRUE(response != NULL);
6434 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6435
6436 TestCompletionCallback callback3;
6437 rv = trans->RestartWithAuth(
6438 AuthCredentials(kFoo, kBar), callback3.callback());
6439 EXPECT_EQ(ERR_IO_PENDING, rv);
6440 rv = callback3.WaitForResult();
6441 EXPECT_EQ(OK, rv);
6442 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6443
6444 response = trans->GetResponseInfo();
6445 ASSERT_TRUE(response != NULL);
6446
6447 // There is no challenge info, since the identity worked.
6448 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6449
6450 EXPECT_EQ(100, response->headers->GetContentLength());
6451
[email protected]ea9dc9a2009-09-05 00:43:326452 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:346453 base::MessageLoop::current()->RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:326454}
6455
[email protected]2217aa22013-10-11 03:03:546456
6457// Test the request-challenge-retry sequence for basic auth when there is a
6458// correct identity in the URL, but its use is being suppressed. The identity
6459// from the URL should never be used.
6460TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
6461 HttpRequestInfo request;
6462 request.method = "GET";
bncce36dca22015-04-21 22:11:236463 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:546464 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
6465
mmenkee65e7af2015-10-13 17:16:426466 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2217aa22013-10-11 03:03:546467 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416468 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2217aa22013-10-11 03:03:546469
6470 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236471 MockWrite(
6472 "GET / HTTP/1.1\r\n"
6473 "Host: www.example.org\r\n"
6474 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:546475 };
6476
6477 MockRead data_reads1[] = {
6478 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6479 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6480 MockRead("Content-Length: 10\r\n\r\n"),
6481 MockRead(SYNCHRONOUS, ERR_FAILED),
6482 };
6483
6484 // After the challenge above, the transaction will be restarted using the
6485 // identity supplied by the user, not the one in the URL, to answer the
6486 // challenge.
6487 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236488 MockWrite(
6489 "GET / HTTP/1.1\r\n"
6490 "Host: www.example.org\r\n"
6491 "Connection: keep-alive\r\n"
6492 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:546493 };
6494
6495 MockRead data_reads3[] = {
6496 MockRead("HTTP/1.0 200 OK\r\n"),
6497 MockRead("Content-Length: 100\r\n\r\n"),
6498 MockRead(SYNCHRONOUS, OK),
6499 };
6500
6501 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6502 data_writes1, arraysize(data_writes1));
6503 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6504 data_writes3, arraysize(data_writes3));
6505 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6506 session_deps_.socket_factory->AddSocketDataProvider(&data3);
6507
6508 TestCompletionCallback callback1;
6509 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6510 EXPECT_EQ(ERR_IO_PENDING, rv);
6511 rv = callback1.WaitForResult();
6512 EXPECT_EQ(OK, rv);
6513 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6514
6515 const HttpResponseInfo* response = trans->GetResponseInfo();
6516 ASSERT_TRUE(response != NULL);
6517 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6518
6519 TestCompletionCallback callback3;
6520 rv = trans->RestartWithAuth(
6521 AuthCredentials(kFoo, kBar), callback3.callback());
6522 EXPECT_EQ(ERR_IO_PENDING, rv);
6523 rv = callback3.WaitForResult();
6524 EXPECT_EQ(OK, rv);
6525 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6526
6527 response = trans->GetResponseInfo();
6528 ASSERT_TRUE(response != NULL);
6529
6530 // There is no challenge info, since the identity worked.
6531 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6532 EXPECT_EQ(100, response->headers->GetContentLength());
6533
6534 // Empty the current queue.
6535 base::MessageLoop::current()->RunUntilIdle();
6536}
6537
[email protected]f9ee6b52008-11-08 06:46:236538// Test that previously tried username/passwords for a realm get re-used.
[email protected]23e482282013-06-14 16:08:026539TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
mmenkee65e7af2015-10-13 17:16:426540 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:236541
6542 // Transaction 1: authenticate (foo, bar) on MyRealm1
6543 {
[email protected]1c773ea12009-04-28 19:58:426544 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236545 request.method = "GET";
bncce36dca22015-04-21 22:11:236546 request.url = GURL("http://www.example.org/x/y/z");
[email protected]f9ee6b52008-11-08 06:46:236547 request.load_flags = 0;
6548
[email protected]262eec82013-03-19 21:01:366549 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506550 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276551
[email protected]f9ee6b52008-11-08 06:46:236552 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236553 MockWrite(
6554 "GET /x/y/z HTTP/1.1\r\n"
6555 "Host: www.example.org\r\n"
6556 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236557 };
6558
6559 MockRead data_reads1[] = {
6560 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6561 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6562 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066563 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236564 };
6565
6566 // Resend with authorization (username=foo, password=bar)
6567 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236568 MockWrite(
6569 "GET /x/y/z HTTP/1.1\r\n"
6570 "Host: www.example.org\r\n"
6571 "Connection: keep-alive\r\n"
6572 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236573 };
6574
6575 // Sever accepts the authorization.
6576 MockRead data_reads2[] = {
6577 MockRead("HTTP/1.0 200 OK\r\n"),
6578 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066579 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236580 };
6581
[email protected]31a2bfe2010-02-09 08:03:396582 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6583 data_writes1, arraysize(data_writes1));
6584 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6585 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076586 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6587 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236588
[email protected]49639fa2011-12-20 23:22:416589 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236590
[email protected]49639fa2011-12-20 23:22:416591 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426592 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236593
6594 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426595 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236596
[email protected]1c773ea12009-04-28 19:58:426597 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506598 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046599 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:236600
[email protected]49639fa2011-12-20 23:22:416601 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:236602
[email protected]49639fa2011-12-20 23:22:416603 rv = trans->RestartWithAuth(
6604 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426605 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236606
6607 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426608 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236609
6610 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506611 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236612 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6613 EXPECT_EQ(100, response->headers->GetContentLength());
6614 }
6615
6616 // ------------------------------------------------------------------------
6617
6618 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
6619 {
[email protected]1c773ea12009-04-28 19:58:426620 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236621 request.method = "GET";
6622 // Note that Transaction 1 was at /x/y/z, so this is in the same
6623 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:236624 request.url = GURL("http://www.example.org/x/y/a/b");
[email protected]f9ee6b52008-11-08 06:46:236625 request.load_flags = 0;
6626
[email protected]262eec82013-03-19 21:01:366627 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506628 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276629
[email protected]f9ee6b52008-11-08 06:46:236630 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236631 MockWrite(
6632 "GET /x/y/a/b HTTP/1.1\r\n"
6633 "Host: www.example.org\r\n"
6634 "Connection: keep-alive\r\n"
6635 // Send preemptive authorization for MyRealm1
6636 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236637 };
6638
6639 // The server didn't like the preemptive authorization, and
6640 // challenges us for a different realm (MyRealm2).
6641 MockRead data_reads1[] = {
6642 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6643 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
6644 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066645 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236646 };
6647
6648 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
6649 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236650 MockWrite(
6651 "GET /x/y/a/b HTTP/1.1\r\n"
6652 "Host: www.example.org\r\n"
6653 "Connection: keep-alive\r\n"
6654 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236655 };
6656
6657 // Sever accepts the authorization.
6658 MockRead data_reads2[] = {
6659 MockRead("HTTP/1.0 200 OK\r\n"),
6660 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066661 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236662 };
6663
[email protected]31a2bfe2010-02-09 08:03:396664 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6665 data_writes1, arraysize(data_writes1));
6666 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6667 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076668 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6669 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236670
[email protected]49639fa2011-12-20 23:22:416671 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236672
[email protected]49639fa2011-12-20 23:22:416673 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426674 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236675
6676 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426677 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236678
[email protected]1c773ea12009-04-28 19:58:426679 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506680 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046681 ASSERT_TRUE(response->auth_challenge.get());
6682 EXPECT_FALSE(response->auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:236683 EXPECT_EQ("www.example.org:80",
[email protected]79cb5c12011-09-12 13:12:046684 response->auth_challenge->challenger.ToString());
6685 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:196686 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:236687
[email protected]49639fa2011-12-20 23:22:416688 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:236689
[email protected]49639fa2011-12-20 23:22:416690 rv = trans->RestartWithAuth(
6691 AuthCredentials(kFoo2, kBar2), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426692 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236693
6694 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426695 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236696
6697 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506698 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236699 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6700 EXPECT_EQ(100, response->headers->GetContentLength());
6701 }
6702
6703 // ------------------------------------------------------------------------
6704
6705 // Transaction 3: Resend a request in MyRealm's protection space --
6706 // succeed with preemptive authorization.
6707 {
[email protected]1c773ea12009-04-28 19:58:426708 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236709 request.method = "GET";
bncce36dca22015-04-21 22:11:236710 request.url = GURL("http://www.example.org/x/y/z2");
[email protected]f9ee6b52008-11-08 06:46:236711 request.load_flags = 0;
6712
[email protected]262eec82013-03-19 21:01:366713 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506714 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276715
[email protected]f9ee6b52008-11-08 06:46:236716 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236717 MockWrite(
6718 "GET /x/y/z2 HTTP/1.1\r\n"
6719 "Host: www.example.org\r\n"
6720 "Connection: keep-alive\r\n"
6721 // The authorization for MyRealm1 gets sent preemptively
6722 // (since the url is in the same protection space)
6723 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236724 };
6725
6726 // Sever accepts the preemptive authorization
6727 MockRead data_reads1[] = {
6728 MockRead("HTTP/1.0 200 OK\r\n"),
6729 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066730 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236731 };
6732
[email protected]31a2bfe2010-02-09 08:03:396733 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6734 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:076735 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:236736
[email protected]49639fa2011-12-20 23:22:416737 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236738
[email protected]49639fa2011-12-20 23:22:416739 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426740 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236741
6742 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426743 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236744
[email protected]1c773ea12009-04-28 19:58:426745 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506746 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236747
6748 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6749 EXPECT_EQ(100, response->headers->GetContentLength());
6750 }
6751
6752 // ------------------------------------------------------------------------
6753
6754 // Transaction 4: request another URL in MyRealm (however the
6755 // url is not known to belong to the protection space, so no pre-auth).
6756 {
[email protected]1c773ea12009-04-28 19:58:426757 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236758 request.method = "GET";
bncce36dca22015-04-21 22:11:236759 request.url = GURL("http://www.example.org/x/1");
[email protected]f9ee6b52008-11-08 06:46:236760 request.load_flags = 0;
6761
[email protected]262eec82013-03-19 21:01:366762 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506763 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276764
[email protected]f9ee6b52008-11-08 06:46:236765 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236766 MockWrite(
6767 "GET /x/1 HTTP/1.1\r\n"
6768 "Host: www.example.org\r\n"
6769 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236770 };
6771
6772 MockRead data_reads1[] = {
6773 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6774 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6775 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066776 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236777 };
6778
6779 // Resend with authorization from MyRealm's cache.
6780 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236781 MockWrite(
6782 "GET /x/1 HTTP/1.1\r\n"
6783 "Host: www.example.org\r\n"
6784 "Connection: keep-alive\r\n"
6785 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236786 };
6787
6788 // Sever accepts the authorization.
6789 MockRead data_reads2[] = {
6790 MockRead("HTTP/1.0 200 OK\r\n"),
6791 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066792 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236793 };
6794
[email protected]31a2bfe2010-02-09 08:03:396795 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6796 data_writes1, arraysize(data_writes1));
6797 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6798 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076799 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6800 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236801
[email protected]49639fa2011-12-20 23:22:416802 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236803
[email protected]49639fa2011-12-20 23:22:416804 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426805 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236806
6807 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426808 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236809
[email protected]0757e7702009-03-27 04:00:226810 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:416811 TestCompletionCallback callback2;
6812 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426813 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:226814 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426815 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226816 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6817
[email protected]1c773ea12009-04-28 19:58:426818 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506819 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236820 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6821 EXPECT_EQ(100, response->headers->GetContentLength());
6822 }
6823
6824 // ------------------------------------------------------------------------
6825
6826 // Transaction 5: request a URL in MyRealm, but the server rejects the
6827 // cached identity. Should invalidate and re-prompt.
6828 {
[email protected]1c773ea12009-04-28 19:58:426829 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236830 request.method = "GET";
bncce36dca22015-04-21 22:11:236831 request.url = GURL("http://www.example.org/p/q/t");
[email protected]f9ee6b52008-11-08 06:46:236832 request.load_flags = 0;
6833
[email protected]262eec82013-03-19 21:01:366834 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506835 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276836
[email protected]f9ee6b52008-11-08 06:46:236837 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236838 MockWrite(
6839 "GET /p/q/t HTTP/1.1\r\n"
6840 "Host: www.example.org\r\n"
6841 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236842 };
6843
6844 MockRead data_reads1[] = {
6845 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6846 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6847 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066848 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236849 };
6850
6851 // Resend with authorization from cache for MyRealm.
6852 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236853 MockWrite(
6854 "GET /p/q/t HTTP/1.1\r\n"
6855 "Host: www.example.org\r\n"
6856 "Connection: keep-alive\r\n"
6857 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236858 };
6859
6860 // Sever rejects the authorization.
6861 MockRead data_reads2[] = {
6862 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6863 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6864 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066865 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236866 };
6867
6868 // At this point we should prompt for new credentials for MyRealm.
6869 // Restart with username=foo3, password=foo4.
6870 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236871 MockWrite(
6872 "GET /p/q/t HTTP/1.1\r\n"
6873 "Host: www.example.org\r\n"
6874 "Connection: keep-alive\r\n"
6875 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236876 };
6877
6878 // Sever accepts the authorization.
6879 MockRead data_reads3[] = {
6880 MockRead("HTTP/1.0 200 OK\r\n"),
6881 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066882 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236883 };
6884
[email protected]31a2bfe2010-02-09 08:03:396885 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6886 data_writes1, arraysize(data_writes1));
6887 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6888 data_writes2, arraysize(data_writes2));
6889 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6890 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:076891 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6892 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6893 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:236894
[email protected]49639fa2011-12-20 23:22:416895 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236896
[email protected]49639fa2011-12-20 23:22:416897 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426898 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236899
6900 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426901 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236902
[email protected]0757e7702009-03-27 04:00:226903 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:416904 TestCompletionCallback callback2;
6905 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426906 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:226907 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426908 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226909 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6910
[email protected]1c773ea12009-04-28 19:58:426911 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506912 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046913 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:236914
[email protected]49639fa2011-12-20 23:22:416915 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:236916
[email protected]49639fa2011-12-20 23:22:416917 rv = trans->RestartWithAuth(
6918 AuthCredentials(kFoo3, kBar3), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:426919 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236920
[email protected]0757e7702009-03-27 04:00:226921 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426922 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236923
6924 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506925 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236926 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6927 EXPECT_EQ(100, response->headers->GetContentLength());
6928 }
6929}
[email protected]89ceba9a2009-03-21 03:46:066930
[email protected]3c32c5f2010-05-18 15:18:126931// Tests that nonce count increments when multiple auth attempts
6932// are started with the same nonce.
[email protected]23e482282013-06-14 16:08:026933TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:446934 HttpAuthHandlerDigest::Factory* digest_factory =
6935 new HttpAuthHandlerDigest::Factory();
6936 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
6937 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6938 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:076939 session_deps_.http_auth_handler_factory.reset(digest_factory);
mmenkee65e7af2015-10-13 17:16:426940 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:126941
6942 // Transaction 1: authenticate (foo, bar) on MyRealm1
6943 {
[email protected]3c32c5f2010-05-18 15:18:126944 HttpRequestInfo request;
6945 request.method = "GET";
bncce36dca22015-04-21 22:11:236946 request.url = GURL("http://www.example.org/x/y/z");
[email protected]3c32c5f2010-05-18 15:18:126947 request.load_flags = 0;
6948
[email protected]262eec82013-03-19 21:01:366949 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506950 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276951
[email protected]3c32c5f2010-05-18 15:18:126952 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236953 MockWrite(
6954 "GET /x/y/z HTTP/1.1\r\n"
6955 "Host: www.example.org\r\n"
6956 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:126957 };
6958
6959 MockRead data_reads1[] = {
6960 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6961 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6962 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066963 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:126964 };
6965
6966 // Resend with authorization (username=foo, password=bar)
6967 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236968 MockWrite(
6969 "GET /x/y/z HTTP/1.1\r\n"
6970 "Host: www.example.org\r\n"
6971 "Connection: keep-alive\r\n"
6972 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6973 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6974 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6975 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:126976 };
6977
6978 // Sever accepts the authorization.
6979 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:086980 MockRead("HTTP/1.0 200 OK\r\n"),
6981 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:126982 };
6983
6984 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6985 data_writes1, arraysize(data_writes1));
6986 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6987 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076988 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6989 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:126990
[email protected]49639fa2011-12-20 23:22:416991 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:126992
[email protected]49639fa2011-12-20 23:22:416993 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:126994 EXPECT_EQ(ERR_IO_PENDING, rv);
6995
6996 rv = callback1.WaitForResult();
6997 EXPECT_EQ(OK, rv);
6998
6999 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507000 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:047001 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
[email protected]3c32c5f2010-05-18 15:18:127002
[email protected]49639fa2011-12-20 23:22:417003 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:127004
[email protected]49639fa2011-12-20 23:22:417005 rv = trans->RestartWithAuth(
7006 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]3c32c5f2010-05-18 15:18:127007 EXPECT_EQ(ERR_IO_PENDING, rv);
7008
7009 rv = callback2.WaitForResult();
7010 EXPECT_EQ(OK, rv);
7011
7012 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507013 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:127014 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7015 }
7016
7017 // ------------------------------------------------------------------------
7018
7019 // Transaction 2: Request another resource in digestive's protection space.
7020 // This will preemptively add an Authorization header which should have an
7021 // "nc" value of 2 (as compared to 1 in the first use.
7022 {
[email protected]3c32c5f2010-05-18 15:18:127023 HttpRequestInfo request;
7024 request.method = "GET";
7025 // Note that Transaction 1 was at /x/y/z, so this is in the same
7026 // protection space as digest.
bncce36dca22015-04-21 22:11:237027 request.url = GURL("http://www.example.org/x/y/a/b");
[email protected]3c32c5f2010-05-18 15:18:127028 request.load_flags = 0;
7029
[email protected]262eec82013-03-19 21:01:367030 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507031 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277032
[email protected]3c32c5f2010-05-18 15:18:127033 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237034 MockWrite(
7035 "GET /x/y/a/b HTTP/1.1\r\n"
7036 "Host: www.example.org\r\n"
7037 "Connection: keep-alive\r\n"
7038 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
7039 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
7040 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
7041 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:127042 };
7043
7044 // Sever accepts the authorization.
7045 MockRead data_reads1[] = {
7046 MockRead("HTTP/1.0 200 OK\r\n"),
7047 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067048 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:127049 };
7050
7051 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7052 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:077053 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:127054
[email protected]49639fa2011-12-20 23:22:417055 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:127056
[email protected]49639fa2011-12-20 23:22:417057 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:127058 EXPECT_EQ(ERR_IO_PENDING, rv);
7059
7060 rv = callback1.WaitForResult();
7061 EXPECT_EQ(OK, rv);
7062
7063 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507064 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:127065 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7066 }
7067}
7068
[email protected]89ceba9a2009-03-21 03:46:067069// Test the ResetStateForRestart() private method.
[email protected]23e482282013-06-14 16:08:027070TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:067071 // Create a transaction (the dependencies aren't important).
mmenkee65e7af2015-10-13 17:16:427072 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:407073 scoped_ptr<HttpNetworkTransaction> trans(
dcheng48459ac22014-08-26 00:46:417074 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]89ceba9a2009-03-21 03:46:067075
7076 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:067077 trans->read_buf_ = new IOBuffer(15);
7078 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:207079 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:067080
7081 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:147082 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:577083 response->auth_challenge = new AuthChallengeInfo();
[email protected]70d66502011-09-23 00:55:087084 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:577085 response->response_time = base::Time::Now();
7086 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:067087
7088 { // Setup state for response_.vary_data
7089 HttpRequestInfo request;
7090 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
7091 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:277092 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:437093 request.extra_headers.SetHeader("Foo", "1");
7094 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:507095 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:067096 }
7097
7098 // Cause the above state to be reset.
7099 trans->ResetStateForRestart();
7100
7101 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:077102 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:067103 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:207104 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:577105 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7106 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:047107 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:087108 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:577109 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:067110}
7111
[email protected]bacff652009-03-31 17:50:337112// Test HTTPS connections to a site with a bad certificate
[email protected]23e482282013-06-14 16:08:027113TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:337114 HttpRequestInfo request;
7115 request.method = "GET";
bncce36dca22015-04-21 22:11:237116 request.url = GURL("https://www.example.org/");
[email protected]bacff652009-03-31 17:50:337117 request.load_flags = 0;
7118
mmenkee65e7af2015-10-13 17:16:427119 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277120 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417121 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277122
[email protected]bacff652009-03-31 17:50:337123 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237124 MockWrite(
7125 "GET / HTTP/1.1\r\n"
7126 "Host: www.example.org\r\n"
7127 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337128 };
7129
7130 MockRead data_reads[] = {
7131 MockRead("HTTP/1.0 200 OK\r\n"),
7132 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7133 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067134 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:337135 };
7136
[email protected]5ecc992a42009-11-11 01:41:597137 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:397138 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7139 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067140 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7141 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:337142
[email protected]bb88e1d32013-05-03 23:11:077143 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7144 session_deps_.socket_factory->AddSocketDataProvider(&data);
7145 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7146 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:337147
[email protected]49639fa2011-12-20 23:22:417148 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:337149
[email protected]49639fa2011-12-20 23:22:417150 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:337151 EXPECT_EQ(ERR_IO_PENDING, rv);
7152
7153 rv = callback.WaitForResult();
7154 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7155
[email protected]49639fa2011-12-20 23:22:417156 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:337157 EXPECT_EQ(ERR_IO_PENDING, rv);
7158
7159 rv = callback.WaitForResult();
7160 EXPECT_EQ(OK, rv);
7161
7162 const HttpResponseInfo* response = trans->GetResponseInfo();
7163
[email protected]fe2255a2011-09-20 19:37:507164 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:337165 EXPECT_EQ(100, response->headers->GetContentLength());
7166}
7167
7168// Test HTTPS connections to a site with a bad certificate, going through a
7169// proxy
[email protected]23e482282013-06-14 16:08:027170TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
rdsmith82957ad2015-09-16 19:42:037171 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]bacff652009-03-31 17:50:337172
7173 HttpRequestInfo request;
7174 request.method = "GET";
bncce36dca22015-04-21 22:11:237175 request.url = GURL("https://www.example.org/");
[email protected]bacff652009-03-31 17:50:337176 request.load_flags = 0;
7177
7178 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:177179 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7180 "Host: www.example.org:443\r\n"
7181 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337182 };
7183
7184 MockRead proxy_reads[] = {
7185 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067186 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:337187 };
7188
7189 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177190 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7191 "Host: www.example.org:443\r\n"
7192 "Proxy-Connection: keep-alive\r\n\r\n"),
7193 MockWrite("GET / HTTP/1.1\r\n"
7194 "Host: www.example.org\r\n"
7195 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337196 };
7197
7198 MockRead data_reads[] = {
7199 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7200 MockRead("HTTP/1.0 200 OK\r\n"),
7201 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7202 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067203 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:337204 };
7205
[email protected]31a2bfe2010-02-09 08:03:397206 StaticSocketDataProvider ssl_bad_certificate(
7207 proxy_reads, arraysize(proxy_reads),
7208 proxy_writes, arraysize(proxy_writes));
7209 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7210 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067211 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7212 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:337213
[email protected]bb88e1d32013-05-03 23:11:077214 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7215 session_deps_.socket_factory->AddSocketDataProvider(&data);
7216 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7217 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:337218
[email protected]49639fa2011-12-20 23:22:417219 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:337220
7221 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:077222 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:337223
mmenkee65e7af2015-10-13 17:16:427224 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:407225 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417226 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bacff652009-03-31 17:50:337227
[email protected]49639fa2011-12-20 23:22:417228 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:337229 EXPECT_EQ(ERR_IO_PENDING, rv);
7230
7231 rv = callback.WaitForResult();
7232 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7233
[email protected]49639fa2011-12-20 23:22:417234 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:337235 EXPECT_EQ(ERR_IO_PENDING, rv);
7236
7237 rv = callback.WaitForResult();
7238 EXPECT_EQ(OK, rv);
7239
7240 const HttpResponseInfo* response = trans->GetResponseInfo();
7241
[email protected]fe2255a2011-09-20 19:37:507242 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:337243 EXPECT_EQ(100, response->headers->GetContentLength());
7244 }
7245}
7246
[email protected]2df19bb2010-08-25 20:13:467247
7248// Test HTTPS connections to a site, going through an HTTPS proxy
[email protected]23e482282013-06-14 16:08:027249TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037250 session_deps_.proxy_service =
7251 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:517252 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:077253 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:467254
7255 HttpRequestInfo request;
7256 request.method = "GET";
bncce36dca22015-04-21 22:11:237257 request.url = GURL("https://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467258 request.load_flags = 0;
7259
7260 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177261 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7262 "Host: www.example.org:443\r\n"
7263 "Proxy-Connection: keep-alive\r\n\r\n"),
7264 MockWrite("GET / HTTP/1.1\r\n"
7265 "Host: www.example.org\r\n"
7266 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467267 };
7268
7269 MockRead data_reads[] = {
7270 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7271 MockRead("HTTP/1.1 200 OK\r\n"),
7272 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7273 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067274 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467275 };
7276
7277 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7278 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067279 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
7280 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:467281
[email protected]bb88e1d32013-05-03 23:11:077282 session_deps_.socket_factory->AddSocketDataProvider(&data);
7283 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
7284 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:467285
[email protected]49639fa2011-12-20 23:22:417286 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:467287
mmenkee65e7af2015-10-13 17:16:427288 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:467289 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417290 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2df19bb2010-08-25 20:13:467291
[email protected]49639fa2011-12-20 23:22:417292 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:467293 EXPECT_EQ(ERR_IO_PENDING, rv);
7294
7295 rv = callback.WaitForResult();
7296 EXPECT_EQ(OK, rv);
7297 const HttpResponseInfo* response = trans->GetResponseInfo();
7298
[email protected]fe2255a2011-09-20 19:37:507299 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:467300
7301 EXPECT_TRUE(response->headers->IsKeepAlive());
7302 EXPECT_EQ(200, response->headers->response_code());
7303 EXPECT_EQ(100, response->headers->GetContentLength());
7304 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:207305
7306 LoadTimingInfo load_timing_info;
7307 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7308 TestLoadTimingNotReusedWithPac(load_timing_info,
7309 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:467310}
7311
[email protected]511f6f52010-12-17 03:58:297312// Test an HTTPS Proxy's ability to redirect a CONNECT request
[email protected]23e482282013-06-14 16:08:027313TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037314 session_deps_.proxy_service =
7315 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:517316 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:077317 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:297318
7319 HttpRequestInfo request;
7320 request.method = "GET";
bncce36dca22015-04-21 22:11:237321 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297322 request.load_flags = 0;
7323
7324 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177325 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7326 "Host: www.example.org:443\r\n"
7327 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:297328 };
7329
7330 MockRead data_reads[] = {
7331 MockRead("HTTP/1.1 302 Redirect\r\n"),
7332 MockRead("Location: http://login.example.com/\r\n"),
7333 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067334 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:297335 };
7336
7337 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7338 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067339 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:297340
[email protected]bb88e1d32013-05-03 23:11:077341 session_deps_.socket_factory->AddSocketDataProvider(&data);
7342 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297343
[email protected]49639fa2011-12-20 23:22:417344 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297345
mmenkee65e7af2015-10-13 17:16:427346 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297347 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417348 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297349
[email protected]49639fa2011-12-20 23:22:417350 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297351 EXPECT_EQ(ERR_IO_PENDING, rv);
7352
7353 rv = callback.WaitForResult();
7354 EXPECT_EQ(OK, rv);
7355 const HttpResponseInfo* response = trans->GetResponseInfo();
7356
[email protected]fe2255a2011-09-20 19:37:507357 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:297358
7359 EXPECT_EQ(302, response->headers->response_code());
7360 std::string url;
7361 EXPECT_TRUE(response->headers->IsRedirect(&url));
7362 EXPECT_EQ("http://login.example.com/", url);
[email protected]029c83b62013-01-24 05:28:207363
7364 // In the case of redirects from proxies, HttpNetworkTransaction returns
7365 // timing for the proxy connection instead of the connection to the host,
7366 // and no send / receive times.
7367 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
7368 LoadTimingInfo load_timing_info;
7369 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7370
7371 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:297372 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:207373
7374 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
7375 EXPECT_LE(load_timing_info.proxy_resolve_start,
7376 load_timing_info.proxy_resolve_end);
7377 EXPECT_LE(load_timing_info.proxy_resolve_end,
7378 load_timing_info.connect_timing.connect_start);
7379 ExpectConnectTimingHasTimes(
7380 load_timing_info.connect_timing,
7381 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
7382
7383 EXPECT_TRUE(load_timing_info.send_start.is_null());
7384 EXPECT_TRUE(load_timing_info.send_end.is_null());
7385 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]511f6f52010-12-17 03:58:297386}
7387
7388// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
[email protected]23e482282013-06-14 16:08:027389TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
rdsmith82957ad2015-09-16 19:42:037390 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297391
7392 HttpRequestInfo request;
7393 request.method = "GET";
bncce36dca22015-04-21 22:11:237394 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297395 request.load_flags = 0;
7396
lgarrona91df87f2014-12-05 00:51:347397 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237398 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207399 scoped_ptr<SpdyFrame> goaway(
7400 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]511f6f52010-12-17 03:58:297401 MockWrite data_writes[] = {
rch8e6c6c42015-05-01 14:05:137402 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
7403 CreateMockWrite(*goaway.get(), 2, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:297404 };
7405
7406 static const char* const kExtraHeaders[] = {
7407 "location",
7408 "http://login.example.com/",
7409 };
[email protected]ff98d7f02012-03-22 21:44:197410 scoped_ptr<SpdyFrame> resp(
[email protected]23e482282013-06-14 16:08:027411 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
[email protected]511f6f52010-12-17 03:58:297412 arraysize(kExtraHeaders)/2, 1));
7413 MockRead data_reads[] = {
rch8e6c6c42015-05-01 14:05:137414 CreateMockRead(*resp.get(), 1), MockRead(ASYNC, 0, 3), // EOF
[email protected]511f6f52010-12-17 03:58:297415 };
7416
rch8e6c6c42015-05-01 14:05:137417 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
7418 arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067419 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
rdsmithebb50aa2015-11-12 03:44:387420 proxy_ssl.SetNextProto(GetProtocol());
[email protected]511f6f52010-12-17 03:58:297421
[email protected]bb88e1d32013-05-03 23:11:077422 session_deps_.socket_factory->AddSocketDataProvider(&data);
7423 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297424
[email protected]49639fa2011-12-20 23:22:417425 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297426
mmenkee65e7af2015-10-13 17:16:427427 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297428 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417429 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297430
[email protected]49639fa2011-12-20 23:22:417431 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297432 EXPECT_EQ(ERR_IO_PENDING, rv);
7433
7434 rv = callback.WaitForResult();
7435 EXPECT_EQ(OK, rv);
7436 const HttpResponseInfo* response = trans->GetResponseInfo();
7437
[email protected]fe2255a2011-09-20 19:37:507438 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:297439
7440 EXPECT_EQ(302, response->headers->response_code());
7441 std::string url;
7442 EXPECT_TRUE(response->headers->IsRedirect(&url));
7443 EXPECT_EQ("http://login.example.com/", url);
7444}
7445
[email protected]4eddbc732012-08-09 05:40:177446// Test that an HTTPS proxy's response to a CONNECT request is filtered.
[email protected]23e482282013-06-14 16:08:027447TEST_P(HttpNetworkTransactionTest,
[email protected]4eddbc732012-08-09 05:40:177448 ErrorResponseToHttpsConnectViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037449 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297450
7451 HttpRequestInfo request;
7452 request.method = "GET";
bncce36dca22015-04-21 22:11:237453 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297454 request.load_flags = 0;
7455
7456 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177457 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7458 "Host: www.example.org:443\r\n"
7459 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:297460 };
7461
7462 MockRead data_reads[] = {
7463 MockRead("HTTP/1.1 404 Not Found\r\n"),
7464 MockRead("Content-Length: 23\r\n\r\n"),
7465 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:067466 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:297467 };
7468
7469 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7470 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067471 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:297472
[email protected]bb88e1d32013-05-03 23:11:077473 session_deps_.socket_factory->AddSocketDataProvider(&data);
7474 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297475
[email protected]49639fa2011-12-20 23:22:417476 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297477
mmenkee65e7af2015-10-13 17:16:427478 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297479 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417480 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297481
[email protected]49639fa2011-12-20 23:22:417482 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297483 EXPECT_EQ(ERR_IO_PENDING, rv);
7484
7485 rv = callback.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:177486 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]511f6f52010-12-17 03:58:297487
[email protected]4eddbc732012-08-09 05:40:177488 // TODO(ttuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:297489}
7490
[email protected]4eddbc732012-08-09 05:40:177491// Test that a SPDY proxy's response to a CONNECT request is filtered.
[email protected]23e482282013-06-14 16:08:027492TEST_P(HttpNetworkTransactionTest,
[email protected]4eddbc732012-08-09 05:40:177493 ErrorResponseToHttpsConnectViaSpdyProxy) {
rdsmith82957ad2015-09-16 19:42:037494 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297495
7496 HttpRequestInfo request;
7497 request.method = "GET";
bncce36dca22015-04-21 22:11:237498 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297499 request.load_flags = 0;
7500
lgarrona91df87f2014-12-05 00:51:347501 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237502 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207503 scoped_ptr<SpdyFrame> rst(
7504 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]511f6f52010-12-17 03:58:297505 MockWrite data_writes[] = {
rch8e6c6c42015-05-01 14:05:137506 CreateMockWrite(*conn.get(), 0), CreateMockWrite(*rst.get(), 3),
[email protected]511f6f52010-12-17 03:58:297507 };
7508
7509 static const char* const kExtraHeaders[] = {
7510 "location",
7511 "http://login.example.com/",
7512 };
[email protected]ff98d7f02012-03-22 21:44:197513 scoped_ptr<SpdyFrame> resp(
[email protected]23e482282013-06-14 16:08:027514 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
[email protected]511f6f52010-12-17 03:58:297515 arraysize(kExtraHeaders)/2, 1));
[email protected]ff98d7f02012-03-22 21:44:197516 scoped_ptr<SpdyFrame> body(
[email protected]23e482282013-06-14 16:08:027517 spdy_util_.ConstructSpdyBodyFrame(
7518 1, "The host does not exist", 23, true));
[email protected]511f6f52010-12-17 03:58:297519 MockRead data_reads[] = {
rch8e6c6c42015-05-01 14:05:137520 CreateMockRead(*resp.get(), 1),
7521 CreateMockRead(*body.get(), 2),
7522 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:297523 };
7524
rch8e6c6c42015-05-01 14:05:137525 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
7526 arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067527 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
rdsmithebb50aa2015-11-12 03:44:387528 proxy_ssl.SetNextProto(GetProtocol());
[email protected]511f6f52010-12-17 03:58:297529
[email protected]bb88e1d32013-05-03 23:11:077530 session_deps_.socket_factory->AddSocketDataProvider(&data);
7531 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297532
[email protected]49639fa2011-12-20 23:22:417533 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297534
mmenkee65e7af2015-10-13 17:16:427535 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297536 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417537 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297538
[email protected]49639fa2011-12-20 23:22:417539 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297540 EXPECT_EQ(ERR_IO_PENDING, rv);
7541
7542 rv = callback.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:177543 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]511f6f52010-12-17 03:58:297544
[email protected]4eddbc732012-08-09 05:40:177545 // TODO(ttuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:297546}
7547
[email protected]0c5fb722012-02-28 11:50:357548// Test the request-challenge-retry sequence for basic auth, through
7549// a SPDY proxy over a single SPDY session.
[email protected]23e482282013-06-14 16:08:027550TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:357551 HttpRequestInfo request;
7552 request.method = "GET";
bncce36dca22015-04-21 22:11:237553 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:357554 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:297555 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]0c5fb722012-02-28 11:50:357556
7557 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037558 session_deps_.proxy_service =
7559 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
vishal.b62985ca92015-04-17 08:45:517560 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077561 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:427562 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:357563
7564 // Since we have proxy, should try to establish tunnel.
lgarrona91df87f2014-12-05 00:51:347565 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237566 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207567 scoped_ptr<SpdyFrame> rst(
7568 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
rdsmithebb50aa2015-11-12 03:44:387569 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:357570
7571 // After calling trans->RestartWithAuth(), this is the request we should
7572 // be issuing -- the final header line contains the credentials.
7573 const char* const kAuthCredentials[] = {
7574 "proxy-authorization", "Basic Zm9vOmJhcg==",
7575 };
[email protected]fba2dbde2013-05-24 16:09:017576 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
lgarrona91df87f2014-12-05 00:51:347577 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
bncce36dca22015-04-21 22:11:237578 HostPortPair("www.example.org", 443)));
7579 // fetch https://www.example.org/ via HTTP
7580 const char get[] =
7581 "GET / HTTP/1.1\r\n"
7582 "Host: www.example.org\r\n"
7583 "Connection: keep-alive\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:197584 scoped_ptr<SpdyFrame> wrapped_get(
[email protected]23e482282013-06-14 16:08:027585 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
[email protected]0c5fb722012-02-28 11:50:357586
7587 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137588 CreateMockWrite(*req, 0, ASYNC),
7589 CreateMockWrite(*rst, 2, ASYNC),
7590 CreateMockWrite(*connect2, 3),
7591 CreateMockWrite(*wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:357592 };
7593
7594 // The proxy responds to the connect with a 407, using a persistent
7595 // connection.
thestig9d3bb0c2015-01-24 00:49:517596 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:357597 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:357598 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
7599 };
[email protected]745aa9c2014-06-27 02:21:297600 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
7601 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:357602
[email protected]23e482282013-06-14 16:08:027603 scoped_ptr<SpdyFrame> conn_resp(
7604 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]0c5fb722012-02-28 11:50:357605 const char resp[] = "HTTP/1.1 200 OK\r\n"
7606 "Content-Length: 5\r\n\r\n";
7607
[email protected]ff98d7f02012-03-22 21:44:197608 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:027609 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
[email protected]ff98d7f02012-03-22 21:44:197610 scoped_ptr<SpdyFrame> wrapped_body(
[email protected]23e482282013-06-14 16:08:027611 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
[email protected]0c5fb722012-02-28 11:50:357612 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137613 CreateMockRead(*conn_auth_resp, 1, ASYNC),
7614 CreateMockRead(*conn_resp, 4, ASYNC),
7615 CreateMockRead(*wrapped_get_resp, 6, ASYNC),
7616 CreateMockRead(*wrapped_body, 7, ASYNC),
7617 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:357618 };
7619
rch8e6c6c42015-05-01 14:05:137620 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7621 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077622 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:357623 // Negotiate SPDY to the proxy
7624 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387625 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077626 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:357627 // Vanilla SSL to the server
7628 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077629 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:357630
7631 TestCompletionCallback callback1;
7632
[email protected]262eec82013-03-19 21:01:367633 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507634 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0c5fb722012-02-28 11:50:357635
7636 int rv = trans->Start(&request, callback1.callback(), log.bound());
7637 EXPECT_EQ(ERR_IO_PENDING, rv);
7638
7639 rv = callback1.WaitForResult();
7640 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:467641 TestNetLogEntry::List entries;
[email protected]0c5fb722012-02-28 11:50:357642 log.GetEntries(&entries);
7643 size_t pos = ExpectLogContainsSomewhere(
7644 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7645 NetLog::PHASE_NONE);
7646 ExpectLogContainsSomewhere(
7647 entries, pos,
7648 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7649 NetLog::PHASE_NONE);
7650
7651 const HttpResponseInfo* response = trans->GetResponseInfo();
7652 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:507653 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]0c5fb722012-02-28 11:50:357654 EXPECT_EQ(407, response->headers->response_code());
7655 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7656 EXPECT_TRUE(response->auth_challenge.get() != NULL);
7657 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
7658
7659 TestCompletionCallback callback2;
7660
7661 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
7662 callback2.callback());
7663 EXPECT_EQ(ERR_IO_PENDING, rv);
7664
7665 rv = callback2.WaitForResult();
7666 EXPECT_EQ(OK, rv);
7667
7668 response = trans->GetResponseInfo();
7669 ASSERT_TRUE(response != NULL);
7670
7671 EXPECT_TRUE(response->headers->IsKeepAlive());
7672 EXPECT_EQ(200, response->headers->response_code());
7673 EXPECT_EQ(5, response->headers->GetContentLength());
7674 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7675
7676 // The password prompt info should not be set.
7677 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7678
[email protected]029c83b62013-01-24 05:28:207679 LoadTimingInfo load_timing_info;
7680 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7681 TestLoadTimingNotReusedWithPac(load_timing_info,
7682 CONNECT_TIMING_HAS_SSL_TIMES);
7683
[email protected]0c5fb722012-02-28 11:50:357684 trans.reset();
7685 session->CloseAllConnections();
7686}
7687
[email protected]7c6f7ba2012-04-03 04:09:297688// Test that an explicitly trusted SPDY proxy can push a resource from an
7689// origin that is different from that of its associated resource.
[email protected]23e482282013-06-14 16:08:027690TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
[email protected]7c6f7ba2012-04-03 04:09:297691 HttpRequestInfo request;
7692 HttpRequestInfo push_request;
7693
[email protected]7c6f7ba2012-04-03 04:09:297694 request.method = "GET";
bncce36dca22015-04-21 22:11:237695 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:297696 push_request.method = "GET";
7697 push_request.url = GURL("http://www.another-origin.com/foo.dat");
7698
[email protected]7c6f7ba2012-04-03 04:09:297699 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037700 session_deps_.proxy_service =
7701 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
vishal.b62985ca92015-04-17 08:45:517702 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077703 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:507704
7705 // Enable cross-origin push.
[email protected]bb88e1d32013-05-03 23:11:077706 session_deps_.trusted_spdy_proxy = "myproxy:70";
[email protected]61b4efc2012-04-27 18:12:507707
mmenkee65e7af2015-10-13 17:16:427708 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:297709
[email protected]cdf8f7e72013-05-23 10:56:467710 scoped_ptr<SpdyFrame> stream1_syn(
7711 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
[email protected]7c6f7ba2012-04-03 04:09:297712
7713 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137714 CreateMockWrite(*stream1_syn, 0, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:297715 };
7716
7717 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027718 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:297719
7720 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027721 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:297722
7723 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027724 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]7c6f7ba2012-04-03 04:09:297725 0,
7726 2,
7727 1,
7728 "http://www.another-origin.com/foo.dat"));
[email protected]8a0fc822013-06-27 20:52:437729 const char kPushedData[] = "pushed";
7730 scoped_ptr<SpdyFrame> stream2_body(
7731 spdy_util_.ConstructSpdyBodyFrame(
7732 2, kPushedData, strlen(kPushedData), true));
[email protected]7c6f7ba2012-04-03 04:09:297733
7734 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137735 CreateMockRead(*stream1_reply, 1, ASYNC),
7736 CreateMockRead(*stream2_syn, 2, ASYNC),
7737 CreateMockRead(*stream1_body, 3, ASYNC),
7738 CreateMockRead(*stream2_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:597739 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:297740 };
7741
rch8e6c6c42015-05-01 14:05:137742 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7743 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077744 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:297745 // Negotiate SPDY to the proxy
7746 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387747 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077748 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:297749
[email protected]262eec82013-03-19 21:01:367750 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507751 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7c6f7ba2012-04-03 04:09:297752 TestCompletionCallback callback;
7753 int rv = trans->Start(&request, callback.callback(), log.bound());
7754 EXPECT_EQ(ERR_IO_PENDING, rv);
7755
7756 rv = callback.WaitForResult();
7757 EXPECT_EQ(OK, rv);
7758 const HttpResponseInfo* response = trans->GetResponseInfo();
7759
[email protected]262eec82013-03-19 21:01:367760 scoped_ptr<HttpTransaction> push_trans(
[email protected]90499482013-06-01 00:39:507761 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7762 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
[email protected]7c6f7ba2012-04-03 04:09:297763 EXPECT_EQ(ERR_IO_PENDING, rv);
7764
7765 rv = callback.WaitForResult();
7766 EXPECT_EQ(OK, rv);
7767 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
7768
7769 ASSERT_TRUE(response != NULL);
7770 EXPECT_TRUE(response->headers->IsKeepAlive());
7771
7772 EXPECT_EQ(200, response->headers->response_code());
7773 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7774
7775 std::string response_data;
7776 rv = ReadTransaction(trans.get(), &response_data);
7777 EXPECT_EQ(OK, rv);
7778 EXPECT_EQ("hello!", response_data);
7779
[email protected]029c83b62013-01-24 05:28:207780 LoadTimingInfo load_timing_info;
7781 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7782 TestLoadTimingNotReusedWithPac(load_timing_info,
7783 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7784
[email protected]7c6f7ba2012-04-03 04:09:297785 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:507786 EXPECT_TRUE(push_response->headers.get() != NULL);
[email protected]7c6f7ba2012-04-03 04:09:297787 EXPECT_EQ(200, push_response->headers->response_code());
7788
7789 rv = ReadTransaction(push_trans.get(), &response_data);
7790 EXPECT_EQ(OK, rv);
7791 EXPECT_EQ("pushed", response_data);
7792
[email protected]029c83b62013-01-24 05:28:207793 LoadTimingInfo push_load_timing_info;
7794 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
7795 TestLoadTimingReusedWithPac(push_load_timing_info);
7796 // The transactions should share a socket ID, despite being for different
7797 // origins.
7798 EXPECT_EQ(load_timing_info.socket_log_id,
7799 push_load_timing_info.socket_log_id);
7800
[email protected]7c6f7ba2012-04-03 04:09:297801 trans.reset();
7802 push_trans.reset();
7803 session->CloseAllConnections();
7804}
7805
[email protected]8c843192012-04-05 07:15:007806// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
[email protected]23e482282013-06-14 16:08:027807TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
[email protected]8c843192012-04-05 07:15:007808 HttpRequestInfo request;
7809
7810 request.method = "GET";
bncce36dca22015-04-21 22:11:237811 request.url = GURL("http://www.example.org/");
[email protected]8c843192012-04-05 07:15:007812
[email protected]8c843192012-04-05 07:15:007813 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037814 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:517815 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077816 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:507817
7818 // Enable cross-origin push.
[email protected]bb88e1d32013-05-03 23:11:077819 session_deps_.trusted_spdy_proxy = "myproxy:70";
[email protected]61b4efc2012-04-27 18:12:507820
mmenkee65e7af2015-10-13 17:16:427821 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:007822
[email protected]cdf8f7e72013-05-23 10:56:467823 scoped_ptr<SpdyFrame> stream1_syn(
7824 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
[email protected]8c843192012-04-05 07:15:007825
7826 scoped_ptr<SpdyFrame> push_rst(
[email protected]c10b20852013-05-15 21:29:207827 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:007828
7829 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137830 CreateMockWrite(*stream1_syn, 0, ASYNC), CreateMockWrite(*push_rst, 3),
[email protected]8c843192012-04-05 07:15:007831 };
7832
7833 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027834 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8c843192012-04-05 07:15:007835
7836 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027837 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]8c843192012-04-05 07:15:007838
7839 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027840 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]8c843192012-04-05 07:15:007841 0,
7842 2,
7843 1,
7844 "https://www.another-origin.com/foo.dat"));
7845
7846 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137847 CreateMockRead(*stream1_reply, 1, ASYNC),
7848 CreateMockRead(*stream2_syn, 2, ASYNC),
7849 CreateMockRead(*stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:597850 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:007851 };
7852
rch8e6c6c42015-05-01 14:05:137853 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7854 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077855 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:007856 // Negotiate SPDY to the proxy
7857 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387858 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077859 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:007860
[email protected]262eec82013-03-19 21:01:367861 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507862 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c843192012-04-05 07:15:007863 TestCompletionCallback callback;
7864 int rv = trans->Start(&request, callback.callback(), log.bound());
7865 EXPECT_EQ(ERR_IO_PENDING, rv);
7866
7867 rv = callback.WaitForResult();
7868 EXPECT_EQ(OK, rv);
7869 const HttpResponseInfo* response = trans->GetResponseInfo();
7870
7871 ASSERT_TRUE(response != NULL);
7872 EXPECT_TRUE(response->headers->IsKeepAlive());
7873
7874 EXPECT_EQ(200, response->headers->response_code());
7875 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7876
7877 std::string response_data;
7878 rv = ReadTransaction(trans.get(), &response_data);
7879 EXPECT_EQ(OK, rv);
7880 EXPECT_EQ("hello!", response_data);
7881
7882 trans.reset();
7883 session->CloseAllConnections();
7884}
7885
[email protected]2df19bb2010-08-25 20:13:467886// Test HTTPS connections to a site with a bad certificate, going through an
7887// HTTPS proxy
[email protected]23e482282013-06-14 16:08:027888TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037889 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]2df19bb2010-08-25 20:13:467890
7891 HttpRequestInfo request;
7892 request.method = "GET";
bncce36dca22015-04-21 22:11:237893 request.url = GURL("https://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467894 request.load_flags = 0;
7895
7896 // Attempt to fetch the URL from a server with a bad cert
7897 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:177898 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7899 "Host: www.example.org:443\r\n"
7900 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467901 };
7902
7903 MockRead bad_cert_reads[] = {
7904 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067905 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:467906 };
7907
7908 // Attempt to fetch the URL with a good cert
7909 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177910 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7911 "Host: www.example.org:443\r\n"
7912 "Proxy-Connection: keep-alive\r\n\r\n"),
7913 MockWrite("GET / HTTP/1.1\r\n"
7914 "Host: www.example.org\r\n"
7915 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467916 };
7917
7918 MockRead good_cert_reads[] = {
7919 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7920 MockRead("HTTP/1.0 200 OK\r\n"),
7921 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7922 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067923 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467924 };
7925
7926 StaticSocketDataProvider ssl_bad_certificate(
7927 bad_cert_reads, arraysize(bad_cert_reads),
7928 bad_cert_writes, arraysize(bad_cert_writes));
7929 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
7930 good_data_writes, arraysize(good_data_writes));
[email protected]8ddf8322012-02-23 18:08:067931 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7932 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:467933
7934 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:077935 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7936 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7937 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:467938
7939 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:077940 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7941 session_deps_.socket_factory->AddSocketDataProvider(&data);
7942 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:467943
[email protected]49639fa2011-12-20 23:22:417944 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:467945
mmenkee65e7af2015-10-13 17:16:427946 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:467947 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417948 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2df19bb2010-08-25 20:13:467949
[email protected]49639fa2011-12-20 23:22:417950 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:467951 EXPECT_EQ(ERR_IO_PENDING, rv);
7952
7953 rv = callback.WaitForResult();
7954 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7955
[email protected]49639fa2011-12-20 23:22:417956 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]2df19bb2010-08-25 20:13:467957 EXPECT_EQ(ERR_IO_PENDING, rv);
7958
7959 rv = callback.WaitForResult();
7960 EXPECT_EQ(OK, rv);
7961
7962 const HttpResponseInfo* response = trans->GetResponseInfo();
7963
[email protected]fe2255a2011-09-20 19:37:507964 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:467965 EXPECT_EQ(100, response->headers->GetContentLength());
7966}
7967
[email protected]23e482282013-06-14 16:08:027968TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:427969 HttpRequestInfo request;
7970 request.method = "GET";
bncce36dca22015-04-21 22:11:237971 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:437972 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7973 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:427974
mmenkee65e7af2015-10-13 17:16:427975 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277976 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417977 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277978
[email protected]1c773ea12009-04-28 19:58:427979 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237980 MockWrite(
7981 "GET / HTTP/1.1\r\n"
7982 "Host: www.example.org\r\n"
7983 "Connection: keep-alive\r\n"
7984 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:427985 };
7986
7987 // Lastly, the server responds with the actual content.
7988 MockRead data_reads[] = {
7989 MockRead("HTTP/1.0 200 OK\r\n"),
7990 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7991 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067992 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:427993 };
7994
[email protected]31a2bfe2010-02-09 08:03:397995 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7996 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:077997 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:427998
[email protected]49639fa2011-12-20 23:22:417999 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428000
[email protected]49639fa2011-12-20 23:22:418001 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428002 EXPECT_EQ(ERR_IO_PENDING, rv);
8003
8004 rv = callback.WaitForResult();
8005 EXPECT_EQ(OK, rv);
8006}
8007
[email protected]23e482282013-06-14 16:08:028008TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:298009 HttpRequestInfo request;
8010 request.method = "GET";
bncce36dca22015-04-21 22:11:238011 request.url = GURL("https://www.example.org/");
[email protected]da81f132010-08-18 23:39:298012 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
8013 "Chromium Ultra Awesome X Edition");
8014
rdsmith82957ad2015-09-16 19:42:038015 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:428016 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278017 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418018 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278019
[email protected]da81f132010-08-18 23:39:298020 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:178021 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8022 "Host: www.example.org:443\r\n"
8023 "Proxy-Connection: keep-alive\r\n"
8024 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]da81f132010-08-18 23:39:298025 };
8026 MockRead data_reads[] = {
8027 // Return an error, so the transaction stops here (this test isn't
8028 // interested in the rest).
8029 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
8030 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8031 MockRead("Proxy-Connection: close\r\n\r\n"),
8032 };
8033
8034 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8035 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078036 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:298037
[email protected]49639fa2011-12-20 23:22:418038 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:298039
[email protected]49639fa2011-12-20 23:22:418040 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]da81f132010-08-18 23:39:298041 EXPECT_EQ(ERR_IO_PENDING, rv);
8042
8043 rv = callback.WaitForResult();
8044 EXPECT_EQ(OK, rv);
8045}
8046
[email protected]23e482282013-06-14 16:08:028047TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:428048 HttpRequestInfo request;
8049 request.method = "GET";
bncce36dca22015-04-21 22:11:238050 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428051 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:168052 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
8053 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:428054
mmenkee65e7af2015-10-13 17:16:428055 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278056 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418057 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278058
[email protected]1c773ea12009-04-28 19:58:428059 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238060 MockWrite(
8061 "GET / HTTP/1.1\r\n"
8062 "Host: www.example.org\r\n"
8063 "Connection: keep-alive\r\n"
8064 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428065 };
8066
8067 // Lastly, the server responds with the actual content.
8068 MockRead data_reads[] = {
8069 MockRead("HTTP/1.0 200 OK\r\n"),
8070 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8071 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068072 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428073 };
8074
[email protected]31a2bfe2010-02-09 08:03:398075 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8076 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078077 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428078
[email protected]49639fa2011-12-20 23:22:418079 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428080
[email protected]49639fa2011-12-20 23:22:418081 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428082 EXPECT_EQ(ERR_IO_PENDING, rv);
8083
8084 rv = callback.WaitForResult();
8085 EXPECT_EQ(OK, rv);
8086}
8087
[email protected]23e482282013-06-14 16:08:028088TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428089 HttpRequestInfo request;
8090 request.method = "POST";
bncce36dca22015-04-21 22:11:238091 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428092
mmenkee65e7af2015-10-13 17:16:428093 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278094 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418095 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278096
[email protected]1c773ea12009-04-28 19:58:428097 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238098 MockWrite(
8099 "POST / HTTP/1.1\r\n"
8100 "Host: www.example.org\r\n"
8101 "Connection: keep-alive\r\n"
8102 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428103 };
8104
8105 // Lastly, the server responds with the actual content.
8106 MockRead data_reads[] = {
8107 MockRead("HTTP/1.0 200 OK\r\n"),
8108 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8109 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068110 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428111 };
8112
[email protected]31a2bfe2010-02-09 08:03:398113 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8114 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078115 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428116
[email protected]49639fa2011-12-20 23:22:418117 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428118
[email protected]49639fa2011-12-20 23:22:418119 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428120 EXPECT_EQ(ERR_IO_PENDING, rv);
8121
8122 rv = callback.WaitForResult();
8123 EXPECT_EQ(OK, rv);
8124}
8125
[email protected]23e482282013-06-14 16:08:028126TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428127 HttpRequestInfo request;
8128 request.method = "PUT";
bncce36dca22015-04-21 22:11:238129 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428130
mmenkee65e7af2015-10-13 17:16:428131 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278132 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418133 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278134
[email protected]1c773ea12009-04-28 19:58:428135 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238136 MockWrite(
8137 "PUT / HTTP/1.1\r\n"
8138 "Host: www.example.org\r\n"
8139 "Connection: keep-alive\r\n"
8140 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428141 };
8142
8143 // Lastly, the server responds with the actual content.
8144 MockRead data_reads[] = {
8145 MockRead("HTTP/1.0 200 OK\r\n"),
8146 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8147 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068148 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428149 };
8150
[email protected]31a2bfe2010-02-09 08:03:398151 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8152 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078153 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428154
[email protected]49639fa2011-12-20 23:22:418155 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428156
[email protected]49639fa2011-12-20 23:22:418157 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428158 EXPECT_EQ(ERR_IO_PENDING, rv);
8159
8160 rv = callback.WaitForResult();
8161 EXPECT_EQ(OK, rv);
8162}
8163
[email protected]23e482282013-06-14 16:08:028164TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428165 HttpRequestInfo request;
8166 request.method = "HEAD";
bncce36dca22015-04-21 22:11:238167 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428168
mmenkee65e7af2015-10-13 17:16:428169 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278170 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418171 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278172
[email protected]1c773ea12009-04-28 19:58:428173 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:138174 MockWrite("HEAD / HTTP/1.1\r\n"
8175 "Host: www.example.org\r\n"
8176 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428177 };
8178
8179 // Lastly, the server responds with the actual content.
8180 MockRead data_reads[] = {
8181 MockRead("HTTP/1.0 200 OK\r\n"),
8182 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8183 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068184 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428185 };
8186
[email protected]31a2bfe2010-02-09 08:03:398187 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8188 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078189 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428190
[email protected]49639fa2011-12-20 23:22:418191 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428192
[email protected]49639fa2011-12-20 23:22:418193 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428194 EXPECT_EQ(ERR_IO_PENDING, rv);
8195
8196 rv = callback.WaitForResult();
8197 EXPECT_EQ(OK, rv);
8198}
8199
[email protected]23e482282013-06-14 16:08:028200TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:428201 HttpRequestInfo request;
8202 request.method = "GET";
bncce36dca22015-04-21 22:11:238203 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428204 request.load_flags = LOAD_BYPASS_CACHE;
8205
mmenkee65e7af2015-10-13 17:16:428206 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278207 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418208 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278209
[email protected]1c773ea12009-04-28 19:58:428210 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238211 MockWrite(
8212 "GET / HTTP/1.1\r\n"
8213 "Host: www.example.org\r\n"
8214 "Connection: keep-alive\r\n"
8215 "Pragma: no-cache\r\n"
8216 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428217 };
8218
8219 // Lastly, the server responds with the actual content.
8220 MockRead data_reads[] = {
8221 MockRead("HTTP/1.0 200 OK\r\n"),
8222 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8223 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068224 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428225 };
8226
[email protected]31a2bfe2010-02-09 08:03:398227 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8228 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078229 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428230
[email protected]49639fa2011-12-20 23:22:418231 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428232
[email protected]49639fa2011-12-20 23:22:418233 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428234 EXPECT_EQ(ERR_IO_PENDING, rv);
8235
8236 rv = callback.WaitForResult();
8237 EXPECT_EQ(OK, rv);
8238}
8239
[email protected]23e482282013-06-14 16:08:028240TEST_P(HttpNetworkTransactionTest,
[email protected]1c773ea12009-04-28 19:58:428241 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:428242 HttpRequestInfo request;
8243 request.method = "GET";
bncce36dca22015-04-21 22:11:238244 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428245 request.load_flags = LOAD_VALIDATE_CACHE;
8246
mmenkee65e7af2015-10-13 17:16:428247 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278248 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418249 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278250
[email protected]1c773ea12009-04-28 19:58:428251 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238252 MockWrite(
8253 "GET / HTTP/1.1\r\n"
8254 "Host: www.example.org\r\n"
8255 "Connection: keep-alive\r\n"
8256 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428257 };
8258
8259 // Lastly, the server responds with the actual content.
8260 MockRead data_reads[] = {
8261 MockRead("HTTP/1.0 200 OK\r\n"),
8262 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8263 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068264 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428265 };
8266
[email protected]31a2bfe2010-02-09 08:03:398267 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8268 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078269 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428270
[email protected]49639fa2011-12-20 23:22:418271 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428272
[email protected]49639fa2011-12-20 23:22:418273 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428274 EXPECT_EQ(ERR_IO_PENDING, rv);
8275
8276 rv = callback.WaitForResult();
8277 EXPECT_EQ(OK, rv);
8278}
8279
[email protected]23e482282013-06-14 16:08:028280TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:428281 HttpRequestInfo request;
8282 request.method = "GET";
bncce36dca22015-04-21 22:11:238283 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438284 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:428285
mmenkee65e7af2015-10-13 17:16:428286 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278287 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418288 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278289
[email protected]1c773ea12009-04-28 19:58:428290 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238291 MockWrite(
8292 "GET / HTTP/1.1\r\n"
8293 "Host: www.example.org\r\n"
8294 "Connection: keep-alive\r\n"
8295 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428296 };
8297
8298 // Lastly, the server responds with the actual content.
8299 MockRead data_reads[] = {
8300 MockRead("HTTP/1.0 200 OK\r\n"),
8301 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8302 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068303 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428304 };
8305
[email protected]31a2bfe2010-02-09 08:03:398306 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8307 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078308 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428309
[email protected]49639fa2011-12-20 23:22:418310 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428311
[email protected]49639fa2011-12-20 23:22:418312 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428313 EXPECT_EQ(ERR_IO_PENDING, rv);
8314
8315 rv = callback.WaitForResult();
8316 EXPECT_EQ(OK, rv);
8317}
8318
[email protected]23e482282013-06-14 16:08:028319TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:478320 HttpRequestInfo request;
8321 request.method = "GET";
bncce36dca22015-04-21 22:11:238322 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438323 request.extra_headers.SetHeader("referer", "www.foo.com");
8324 request.extra_headers.SetHeader("hEllo", "Kitty");
8325 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:478326
mmenkee65e7af2015-10-13 17:16:428327 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278328 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418329 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278330
[email protected]270c6412010-03-29 22:02:478331 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238332 MockWrite(
8333 "GET / HTTP/1.1\r\n"
8334 "Host: www.example.org\r\n"
8335 "Connection: keep-alive\r\n"
8336 "referer: www.foo.com\r\n"
8337 "hEllo: Kitty\r\n"
8338 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:478339 };
8340
8341 // Lastly, the server responds with the actual content.
8342 MockRead data_reads[] = {
8343 MockRead("HTTP/1.0 200 OK\r\n"),
8344 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8345 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068346 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:478347 };
8348
8349 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8350 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078351 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:478352
[email protected]49639fa2011-12-20 23:22:418353 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:478354
[email protected]49639fa2011-12-20 23:22:418355 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]270c6412010-03-29 22:02:478356 EXPECT_EQ(ERR_IO_PENDING, rv);
8357
8358 rv = callback.WaitForResult();
8359 EXPECT_EQ(OK, rv);
8360}
8361
[email protected]23e482282013-06-14 16:08:028362TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278363 HttpRequestInfo request;
8364 request.method = "GET";
bncce36dca22015-04-21 22:11:238365 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278366 request.load_flags = 0;
8367
rdsmith82957ad2015-09-16 19:42:038368 session_deps_.proxy_service =
8369 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518370 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078371 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028372
mmenkee65e7af2015-10-13 17:16:428373 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3cd17242009-06-23 02:59:028374 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418375 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028376
[email protected]3cd17242009-06-23 02:59:028377 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8378 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8379
8380 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238381 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8382 MockWrite(
8383 "GET / HTTP/1.1\r\n"
8384 "Host: www.example.org\r\n"
8385 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028386
8387 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:068388 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:028389 MockRead("HTTP/1.0 200 OK\r\n"),
8390 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8391 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068392 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028393 };
8394
[email protected]31a2bfe2010-02-09 08:03:398395 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8396 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078397 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028398
[email protected]49639fa2011-12-20 23:22:418399 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028400
[email protected]49639fa2011-12-20 23:22:418401 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:028402 EXPECT_EQ(ERR_IO_PENDING, rv);
8403
8404 rv = callback.WaitForResult();
8405 EXPECT_EQ(OK, rv);
8406
8407 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508408 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:028409
[email protected]029c83b62013-01-24 05:28:208410 LoadTimingInfo load_timing_info;
8411 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8412 TestLoadTimingNotReusedWithPac(load_timing_info,
8413 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8414
[email protected]3cd17242009-06-23 02:59:028415 std::string response_text;
8416 rv = ReadTransaction(trans.get(), &response_text);
8417 EXPECT_EQ(OK, rv);
8418 EXPECT_EQ("Payload", response_text);
8419}
8420
[email protected]23e482282013-06-14 16:08:028421TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278422 HttpRequestInfo request;
8423 request.method = "GET";
bncce36dca22015-04-21 22:11:238424 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278425 request.load_flags = 0;
8426
rdsmith82957ad2015-09-16 19:42:038427 session_deps_.proxy_service =
8428 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518429 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078430 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028431
mmenkee65e7af2015-10-13 17:16:428432 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3cd17242009-06-23 02:59:028433 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418434 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028435
[email protected]3cd17242009-06-23 02:59:028436 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
8437 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8438
8439 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238440 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
8441 arraysize(write_buffer)),
8442 MockWrite(
8443 "GET / HTTP/1.1\r\n"
8444 "Host: www.example.org\r\n"
8445 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028446
8447 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018448 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
8449 arraysize(read_buffer)),
[email protected]e0c27be2009-07-15 13:09:358450 MockRead("HTTP/1.0 200 OK\r\n"),
8451 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8452 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068453 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358454 };
8455
[email protected]31a2bfe2010-02-09 08:03:398456 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8457 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078458 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358459
[email protected]8ddf8322012-02-23 18:08:068460 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078461 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:358462
[email protected]49639fa2011-12-20 23:22:418463 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358464
[email protected]49639fa2011-12-20 23:22:418465 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:358466 EXPECT_EQ(ERR_IO_PENDING, rv);
8467
8468 rv = callback.WaitForResult();
8469 EXPECT_EQ(OK, rv);
8470
[email protected]029c83b62013-01-24 05:28:208471 LoadTimingInfo load_timing_info;
8472 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8473 TestLoadTimingNotReusedWithPac(load_timing_info,
8474 CONNECT_TIMING_HAS_SSL_TIMES);
8475
[email protected]e0c27be2009-07-15 13:09:358476 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508477 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:358478
8479 std::string response_text;
8480 rv = ReadTransaction(trans.get(), &response_text);
8481 EXPECT_EQ(OK, rv);
8482 EXPECT_EQ("Payload", response_text);
8483}
8484
[email protected]23e482282013-06-14 16:08:028485TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:208486 HttpRequestInfo request;
8487 request.method = "GET";
bncce36dca22015-04-21 22:11:238488 request.url = GURL("http://www.example.org/");
[email protected]029c83b62013-01-24 05:28:208489 request.load_flags = 0;
8490
rdsmith82957ad2015-09-16 19:42:038491 session_deps_.proxy_service =
8492 ProxyService::CreateFixed("socks4://myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518493 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078494 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:208495
mmenkee65e7af2015-10-13 17:16:428496 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:208497 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418498 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:208499
8500 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8501 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8502
8503 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238504 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8505 MockWrite(
8506 "GET / HTTP/1.1\r\n"
8507 "Host: www.example.org\r\n"
8508 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:208509
8510 MockRead data_reads[] = {
8511 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
8512 MockRead("HTTP/1.0 200 OK\r\n"),
8513 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8514 MockRead("Payload"),
8515 MockRead(SYNCHRONOUS, OK)
8516 };
8517
8518 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8519 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078520 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:208521
8522 TestCompletionCallback callback;
8523
8524 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8525 EXPECT_EQ(ERR_IO_PENDING, rv);
8526
8527 rv = callback.WaitForResult();
8528 EXPECT_EQ(OK, rv);
8529
8530 const HttpResponseInfo* response = trans->GetResponseInfo();
8531 ASSERT_TRUE(response != NULL);
8532
8533 LoadTimingInfo load_timing_info;
8534 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8535 TestLoadTimingNotReused(load_timing_info,
8536 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8537
8538 std::string response_text;
8539 rv = ReadTransaction(trans.get(), &response_text);
8540 EXPECT_EQ(OK, rv);
8541 EXPECT_EQ("Payload", response_text);
8542}
8543
[email protected]23e482282013-06-14 16:08:028544TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278545 HttpRequestInfo request;
8546 request.method = "GET";
bncce36dca22015-04-21 22:11:238547 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278548 request.load_flags = 0;
8549
rdsmith82957ad2015-09-16 19:42:038550 session_deps_.proxy_service =
8551 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518552 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078553 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358554
mmenkee65e7af2015-10-13 17:16:428555 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e0c27be2009-07-15 13:09:358556 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418557 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358558
[email protected]e0c27be2009-07-15 13:09:358559 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8560 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378561 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238562 0x05, // Version
8563 0x01, // Command (CONNECT)
8564 0x00, // Reserved.
8565 0x03, // Address type (DOMAINNAME).
8566 0x0F, // Length of domain (15)
8567 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8568 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:378569 };
[email protected]e0c27be2009-07-15 13:09:358570 const char kSOCKS5OkResponse[] =
8571 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
8572
8573 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238574 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8575 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
8576 MockWrite(
8577 "GET / HTTP/1.1\r\n"
8578 "Host: www.example.org\r\n"
8579 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358580
8581 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018582 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8583 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]e0c27be2009-07-15 13:09:358584 MockRead("HTTP/1.0 200 OK\r\n"),
8585 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8586 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068587 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358588 };
8589
[email protected]31a2bfe2010-02-09 08:03:398590 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8591 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078592 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358593
[email protected]49639fa2011-12-20 23:22:418594 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358595
[email protected]49639fa2011-12-20 23:22:418596 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:358597 EXPECT_EQ(ERR_IO_PENDING, rv);
8598
8599 rv = callback.WaitForResult();
8600 EXPECT_EQ(OK, rv);
8601
8602 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508603 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:358604
[email protected]029c83b62013-01-24 05:28:208605 LoadTimingInfo load_timing_info;
8606 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8607 TestLoadTimingNotReusedWithPac(load_timing_info,
8608 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8609
[email protected]e0c27be2009-07-15 13:09:358610 std::string response_text;
8611 rv = ReadTransaction(trans.get(), &response_text);
8612 EXPECT_EQ(OK, rv);
8613 EXPECT_EQ("Payload", response_text);
8614}
8615
[email protected]23e482282013-06-14 16:08:028616TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278617 HttpRequestInfo request;
8618 request.method = "GET";
bncce36dca22015-04-21 22:11:238619 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278620 request.load_flags = 0;
8621
rdsmith82957ad2015-09-16 19:42:038622 session_deps_.proxy_service =
8623 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518624 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078625 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358626
mmenkee65e7af2015-10-13 17:16:428627 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e0c27be2009-07-15 13:09:358628 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418629 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358630
[email protected]e0c27be2009-07-15 13:09:358631 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8632 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378633 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238634 0x05, // Version
8635 0x01, // Command (CONNECT)
8636 0x00, // Reserved.
8637 0x03, // Address type (DOMAINNAME).
8638 0x0F, // Length of domain (15)
8639 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8640 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:378641 };
8642
[email protected]e0c27be2009-07-15 13:09:358643 const char kSOCKS5OkResponse[] =
8644 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
8645
8646 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238647 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8648 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
8649 arraysize(kSOCKS5OkRequest)),
8650 MockWrite(
8651 "GET / HTTP/1.1\r\n"
8652 "Host: www.example.org\r\n"
8653 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358654
8655 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018656 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8657 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:028658 MockRead("HTTP/1.0 200 OK\r\n"),
8659 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8660 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068661 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028662 };
8663
[email protected]31a2bfe2010-02-09 08:03:398664 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8665 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078666 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028667
[email protected]8ddf8322012-02-23 18:08:068668 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078669 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:028670
[email protected]49639fa2011-12-20 23:22:418671 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028672
[email protected]49639fa2011-12-20 23:22:418673 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:028674 EXPECT_EQ(ERR_IO_PENDING, rv);
8675
8676 rv = callback.WaitForResult();
8677 EXPECT_EQ(OK, rv);
8678
8679 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508680 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:028681
[email protected]029c83b62013-01-24 05:28:208682 LoadTimingInfo load_timing_info;
8683 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8684 TestLoadTimingNotReusedWithPac(load_timing_info,
8685 CONNECT_TIMING_HAS_SSL_TIMES);
8686
[email protected]3cd17242009-06-23 02:59:028687 std::string response_text;
8688 rv = ReadTransaction(trans.get(), &response_text);
8689 EXPECT_EQ(OK, rv);
8690 EXPECT_EQ("Payload", response_text);
8691}
8692
[email protected]448d4ca52012-03-04 04:12:238693namespace {
8694
[email protected]04e5be32009-06-26 20:00:318695// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:068696
8697struct GroupNameTest {
8698 std::string proxy_server;
8699 std::string url;
8700 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:188701 bool ssl;
[email protected]2d731a32010-04-29 01:04:068702};
8703
mmenkee65e7af2015-10-13 17:16:428704scoped_ptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8a0fc822013-06-27 20:52:438705 NextProto next_proto,
[email protected]bb88e1d32013-05-03 23:11:078706 SpdySessionDependencies* session_deps_) {
mmenkee65e7af2015-10-13 17:16:428707 scoped_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:068708
[email protected]30d4c022013-07-18 22:58:168709 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:538710 session->http_server_properties();
bnccacc0992015-03-20 20:22:228711 AlternativeService alternative_service(
bnc4988e432015-03-31 03:06:258712 AlternateProtocolFromNextProto(next_proto), "", 443);
bnc7dc7e1b42015-07-28 14:43:128713 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:228714 http_server_properties->SetAlternativeService(
bnc7dc7e1b42015-07-28 14:43:128715 HostPortPair("host.with.alternate", 80), alternative_service, 1.0,
8716 expiration);
[email protected]2d731a32010-04-29 01:04:068717
8718 return session;
8719}
8720
mmenkee65e7af2015-10-13 17:16:428721int GroupNameTransactionHelper(const std::string& url,
8722 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:068723 HttpRequestInfo request;
8724 request.method = "GET";
8725 request.url = GURL(url);
8726 request.load_flags = 0;
8727
[email protected]262eec82013-03-19 21:01:368728 scoped_ptr<HttpTransaction> trans(
mmenkee65e7af2015-10-13 17:16:428729 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
[email protected]cb9bf6ca2011-01-28 13:15:278730
[email protected]49639fa2011-12-20 23:22:418731 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:068732
8733 // We do not complete this request, the dtor will clean the transaction up.
[email protected]49639fa2011-12-20 23:22:418734 return trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d731a32010-04-29 01:04:068735}
8736
[email protected]448d4ca52012-03-04 04:12:238737} // namespace
8738
[email protected]23e482282013-06-14 16:08:028739TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
[email protected]2d731a32010-04-29 01:04:068740 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238741 {
8742 "", // unused
8743 "http://www.example.org/direct",
8744 "www.example.org:80",
8745 false,
8746 },
8747 {
8748 "", // unused
8749 "http://[2001:1418:13:1::25]/direct",
8750 "[2001:1418:13:1::25]:80",
8751 false,
8752 },
[email protected]04e5be32009-06-26 20:00:318753
bncce36dca22015-04-21 22:11:238754 // SSL Tests
8755 {
8756 "", // unused
8757 "https://www.example.org/direct_ssl",
8758 "ssl/www.example.org:443",
8759 true,
8760 },
8761 {
8762 "", // unused
8763 "https://[2001:1418:13:1::25]/direct",
8764 "ssl/[2001:1418:13:1::25]:443",
8765 true,
8766 },
8767 {
8768 "", // unused
8769 "http://host.with.alternate/direct",
8770 "ssl/host.with.alternate:443",
8771 true,
8772 },
[email protected]2d731a32010-04-29 01:04:068773 };
[email protected]2ff8b312010-04-26 22:20:548774
bnc55ff9da2015-08-19 18:42:358775 session_deps_.use_alternative_services = true;
[email protected]2d731a32010-04-29 01:04:068776
viettrungluue4a8b882014-10-16 06:17:388777 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038778 session_deps_.proxy_service =
8779 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428780 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388781 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]2d731a32010-04-29 01:04:068782
mmenkee65e7af2015-10-13 17:16:428783 HttpNetworkSessionPeer peer(session.get());
[email protected]ab739042011-04-07 15:22:288784 CaptureGroupNameTransportSocketPool* transport_conn_pool =
8785 new CaptureGroupNameTransportSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138786 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348787 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]831e4a32013-11-14 02:14:448788 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8789 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028790 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
8791 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
dchengc7eeda422015-12-26 03:56:488792 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:068793
8794 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428795 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188796 if (tests[i].ssl)
8797 EXPECT_EQ(tests[i].expected_group_name,
8798 ssl_conn_pool->last_group_name_received());
8799 else
8800 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:288801 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:068802 }
[email protected]2d731a32010-04-29 01:04:068803}
8804
[email protected]23e482282013-06-14 16:08:028805TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
[email protected]2d731a32010-04-29 01:04:068806 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238807 {
8808 "http_proxy",
8809 "http://www.example.org/http_proxy_normal",
8810 "www.example.org:80",
8811 false,
8812 },
[email protected]2d731a32010-04-29 01:04:068813
bncce36dca22015-04-21 22:11:238814 // SSL Tests
8815 {
8816 "http_proxy",
8817 "https://www.example.org/http_connect_ssl",
8818 "ssl/www.example.org:443",
8819 true,
8820 },
[email protected]af3490e2010-10-16 21:02:298821
bncce36dca22015-04-21 22:11:238822 {
8823 "http_proxy",
8824 "http://host.with.alternate/direct",
8825 "ssl/host.with.alternate:443",
8826 true,
8827 },
[email protected]45499252013-01-23 17:12:568828
bncce36dca22015-04-21 22:11:238829 {
8830 "http_proxy",
8831 "ftp://ftp.google.com/http_proxy_normal",
8832 "ftp/ftp.google.com:21",
8833 false,
8834 },
[email protected]2d731a32010-04-29 01:04:068835 };
8836
bnc55ff9da2015-08-19 18:42:358837 session_deps_.use_alternative_services = true;
[email protected]2d731a32010-04-29 01:04:068838
viettrungluue4a8b882014-10-16 06:17:388839 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038840 session_deps_.proxy_service =
8841 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428842 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388843 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]2d731a32010-04-29 01:04:068844
mmenkee65e7af2015-10-13 17:16:428845 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:068846
[email protected]e60e47a2010-07-14 03:37:188847 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:138848 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:348849 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138850 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348851 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:028852
[email protected]831e4a32013-11-14 02:14:448853 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8854 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028855 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
8856 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchengc7eeda422015-12-26 03:56:488857 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:068858
8859 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428860 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188861 if (tests[i].ssl)
8862 EXPECT_EQ(tests[i].expected_group_name,
8863 ssl_conn_pool->last_group_name_received());
8864 else
8865 EXPECT_EQ(tests[i].expected_group_name,
8866 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:068867 }
[email protected]2d731a32010-04-29 01:04:068868}
8869
[email protected]23e482282013-06-14 16:08:028870TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
[email protected]2d731a32010-04-29 01:04:068871 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238872 {
8873 "socks4://socks_proxy:1080",
8874 "http://www.example.org/socks4_direct",
8875 "socks4/www.example.org:80",
8876 false,
8877 },
8878 {
8879 "socks5://socks_proxy:1080",
8880 "http://www.example.org/socks5_direct",
8881 "socks5/www.example.org:80",
8882 false,
8883 },
[email protected]2d731a32010-04-29 01:04:068884
bncce36dca22015-04-21 22:11:238885 // SSL Tests
8886 {
8887 "socks4://socks_proxy:1080",
8888 "https://www.example.org/socks4_ssl",
8889 "socks4/ssl/www.example.org:443",
8890 true,
8891 },
8892 {
8893 "socks5://socks_proxy:1080",
8894 "https://www.example.org/socks5_ssl",
8895 "socks5/ssl/www.example.org:443",
8896 true,
8897 },
[email protected]af3490e2010-10-16 21:02:298898
bncce36dca22015-04-21 22:11:238899 {
8900 "socks4://socks_proxy:1080",
8901 "http://host.with.alternate/direct",
8902 "socks4/ssl/host.with.alternate:443",
8903 true,
8904 },
[email protected]04e5be32009-06-26 20:00:318905 };
8906
bnc55ff9da2015-08-19 18:42:358907 session_deps_.use_alternative_services = true;
[email protected]2ff8b312010-04-26 22:20:548908
viettrungluue4a8b882014-10-16 06:17:388909 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038910 session_deps_.proxy_service =
8911 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428912 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388913 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]8b114dd72011-03-25 05:33:028914
mmenkee65e7af2015-10-13 17:16:428915 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:318916
[email protected]e60e47a2010-07-14 03:37:188917 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:138918 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348919 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138920 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348921 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:028922
[email protected]831e4a32013-11-14 02:14:448923 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8924 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028925 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
8926 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchengc7eeda422015-12-26 03:56:488927 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:318928
[email protected]262eec82013-03-19 21:01:368929 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:508930 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]04e5be32009-06-26 20:00:318931
[email protected]2d731a32010-04-29 01:04:068932 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428933 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188934 if (tests[i].ssl)
8935 EXPECT_EQ(tests[i].expected_group_name,
8936 ssl_conn_pool->last_group_name_received());
8937 else
8938 EXPECT_EQ(tests[i].expected_group_name,
8939 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:318940 }
8941}
8942
[email protected]23e482282013-06-14 16:08:028943TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:278944 HttpRequestInfo request;
8945 request.method = "GET";
bncce36dca22015-04-21 22:11:238946 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278947
rdsmith82957ad2015-09-16 19:42:038948 session_deps_.proxy_service =
8949 ProxyService::CreateFixed("myproxy:70;foobar:80");
[email protected]b59ff372009-07-15 22:04:328950
[email protected]69719062010-01-05 20:09:218951 // This simulates failure resolving all hostnames; that means we will fail
8952 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:078953 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:328954
mmenkee65e7af2015-10-13 17:16:428955 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]9172a982009-06-06 00:30:258956 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418957 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]9172a982009-06-06 00:30:258958
[email protected]49639fa2011-12-20 23:22:418959 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:258960
[email protected]49639fa2011-12-20 23:22:418961 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9172a982009-06-06 00:30:258962 EXPECT_EQ(ERR_IO_PENDING, rv);
8963
[email protected]9172a982009-06-06 00:30:258964 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:018965 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:258966}
8967
[email protected]685af592010-05-11 19:31:248968// Base test to make sure that when the load flags for a request specify to
8969// bypass the cache, the DNS cache is not used.
[email protected]23e482282013-06-14 16:08:028970void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
[email protected]bb88e1d32013-05-03 23:11:078971 int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:278972 // Issue a request, asking to bypass the cache(s).
8973 HttpRequestInfo request;
8974 request.method = "GET";
8975 request.load_flags = load_flags;
bncce36dca22015-04-21 22:11:238976 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278977
[email protected]a2c2fb92009-07-18 07:31:048978 // Select a host resolver that does caching.
[email protected]bb88e1d32013-05-03 23:11:078979 session_deps_.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:328980
mmenkee65e7af2015-10-13 17:16:428981 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:078982 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418983 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3b9cca42009-06-16 01:08:288984
bncce36dca22015-04-21 22:11:238985 // Warm up the host cache so it has an entry for "www.example.org".
[email protected]3b9cca42009-06-16 01:08:288986 AddressList addrlist;
[email protected]aa22b242011-11-16 18:58:298987 TestCompletionCallback callback;
[email protected]bb88e1d32013-05-03 23:11:078988 int rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:238989 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8990 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:478991 EXPECT_EQ(ERR_IO_PENDING, rv);
8992 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:288993 EXPECT_EQ(OK, rv);
8994
8995 // Verify that it was added to host cache, by doing a subsequent async lookup
8996 // and confirming it completes synchronously.
[email protected]bb88e1d32013-05-03 23:11:078997 rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:238998 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8999 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:329000 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:289001
bncce36dca22015-04-21 22:11:239002 // Inject a failure the next time that "www.example.org" is resolved. This way
[email protected]3b9cca42009-06-16 01:08:289003 // we can tell if the next lookup hit the cache, or the "network".
9004 // (cache --> success, "network" --> failure).
bncce36dca22015-04-21 22:11:239005 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
[email protected]3b9cca42009-06-16 01:08:289006
9007 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
9008 // first read -- this won't be reached as the host resolution will fail first.
[email protected]8ddf8322012-02-23 18:08:069009 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:399010 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079011 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:289012
[email protected]3b9cca42009-06-16 01:08:289013 // Run the request.
[email protected]49639fa2011-12-20 23:22:419014 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:289015 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419016 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:289017
9018 // If we bypassed the cache, we would have gotten a failure while resolving
bncce36dca22015-04-21 22:11:239019 // "www.example.org".
[email protected]3b9cca42009-06-16 01:08:289020 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
9021}
9022
[email protected]685af592010-05-11 19:31:249023// There are multiple load flags that should trigger the host cache bypass.
9024// Test each in isolation:
[email protected]23e482282013-06-14 16:08:029025TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
[email protected]685af592010-05-11 19:31:249026 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
9027}
9028
[email protected]23e482282013-06-14 16:08:029029TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
[email protected]685af592010-05-11 19:31:249030 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
9031}
9032
[email protected]23e482282013-06-14 16:08:029033TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
[email protected]685af592010-05-11 19:31:249034 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
9035}
9036
[email protected]0877e3d2009-10-17 22:29:579037// Make sure we can handle an error when writing the request.
[email protected]23e482282013-06-14 16:08:029038TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:579039 HttpRequestInfo request;
9040 request.method = "GET";
9041 request.url = GURL("http://www.foo.com/");
9042 request.load_flags = 0;
9043
9044 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:069045 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:579046 };
[email protected]31a2bfe2010-02-09 08:03:399047 StaticSocketDataProvider data(NULL, 0,
9048 write_failure, arraysize(write_failure));
[email protected]bb88e1d32013-05-03 23:11:079049 session_deps_.socket_factory->AddSocketDataProvider(&data);
mmenkee65e7af2015-10-13 17:16:429050 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579051
[email protected]49639fa2011-12-20 23:22:419052 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579053
9054 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419055 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579056
[email protected]49639fa2011-12-20 23:22:419057 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579058 EXPECT_EQ(ERR_IO_PENDING, rv);
9059
9060 rv = callback.WaitForResult();
9061 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
ttuttled9dbc652015-09-29 20:00:599062
9063 IPEndPoint endpoint;
9064 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
9065 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:579066}
9067
zmo9528c9f42015-08-04 22:12:089068// Check that a connection closed after the start of the headers finishes ok.
9069TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:579070 HttpRequestInfo request;
9071 request.method = "GET";
9072 request.url = GURL("http://www.foo.com/");
9073 request.load_flags = 0;
9074
9075 MockRead data_reads[] = {
9076 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:069077 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:579078 };
9079
[email protected]31a2bfe2010-02-09 08:03:399080 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079081 session_deps_.socket_factory->AddSocketDataProvider(&data);
mmenkee65e7af2015-10-13 17:16:429082 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579083
[email protected]49639fa2011-12-20 23:22:419084 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579085
9086 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419087 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579088
[email protected]49639fa2011-12-20 23:22:419089 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579090 EXPECT_EQ(ERR_IO_PENDING, rv);
9091
9092 rv = callback.WaitForResult();
zmo9528c9f42015-08-04 22:12:089093 EXPECT_EQ(OK, rv);
9094
9095 const HttpResponseInfo* response = trans->GetResponseInfo();
9096 ASSERT_TRUE(response != NULL);
9097
9098 EXPECT_TRUE(response->headers.get() != NULL);
9099 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9100
9101 std::string response_data;
9102 rv = ReadTransaction(trans.get(), &response_data);
9103 EXPECT_EQ(OK, rv);
9104 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:599105
9106 IPEndPoint endpoint;
9107 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
9108 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:579109}
9110
9111// Make sure that a dropped connection while draining the body for auth
9112// restart does the right thing.
[email protected]23e482282013-06-14 16:08:029113TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:579114 HttpRequestInfo request;
9115 request.method = "GET";
bncce36dca22015-04-21 22:11:239116 request.url = GURL("http://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:579117 request.load_flags = 0;
9118
9119 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239120 MockWrite(
9121 "GET / HTTP/1.1\r\n"
9122 "Host: www.example.org\r\n"
9123 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:579124 };
9125
9126 MockRead data_reads1[] = {
9127 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
9128 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9129 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9130 MockRead("Content-Length: 14\r\n\r\n"),
9131 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:069132 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:579133 };
9134
[email protected]31a2bfe2010-02-09 08:03:399135 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9136 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:079137 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:579138
9139 // After calling trans->RestartWithAuth(), this is the request we should
9140 // be issuing -- the final header line contains the credentials.
9141 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239142 MockWrite(
9143 "GET / HTTP/1.1\r\n"
9144 "Host: www.example.org\r\n"
9145 "Connection: keep-alive\r\n"
9146 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:579147 };
9148
9149 // Lastly, the server responds with the actual content.
9150 MockRead data_reads2[] = {
9151 MockRead("HTTP/1.1 200 OK\r\n"),
9152 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9153 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069154 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:579155 };
9156
[email protected]31a2bfe2010-02-09 08:03:399157 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9158 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:079159 session_deps_.socket_factory->AddSocketDataProvider(&data2);
mmenkee65e7af2015-10-13 17:16:429160 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579161
[email protected]49639fa2011-12-20 23:22:419162 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:579163
[email protected]262eec82013-03-19 21:01:369164 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509165 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509166
[email protected]49639fa2011-12-20 23:22:419167 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579168 EXPECT_EQ(ERR_IO_PENDING, rv);
9169
9170 rv = callback1.WaitForResult();
9171 EXPECT_EQ(OK, rv);
9172
9173 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509174 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049175 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:579176
[email protected]49639fa2011-12-20 23:22:419177 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:579178
[email protected]49639fa2011-12-20 23:22:419179 rv = trans->RestartWithAuth(
9180 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]0877e3d2009-10-17 22:29:579181 EXPECT_EQ(ERR_IO_PENDING, rv);
9182
9183 rv = callback2.WaitForResult();
9184 EXPECT_EQ(OK, rv);
9185
9186 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509187 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:579188 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9189 EXPECT_EQ(100, response->headers->GetContentLength());
9190}
9191
9192// Test HTTPS connections going through a proxy that sends extra data.
[email protected]23e482282013-06-14 16:08:029193TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
rdsmith82957ad2015-09-16 19:42:039194 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]0877e3d2009-10-17 22:29:579195
9196 HttpRequestInfo request;
9197 request.method = "GET";
bncce36dca22015-04-21 22:11:239198 request.url = GURL("https://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:579199 request.load_flags = 0;
9200
9201 MockRead proxy_reads[] = {
9202 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:069203 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:579204 };
9205
[email protected]31a2bfe2010-02-09 08:03:399206 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]8ddf8322012-02-23 18:08:069207 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:579208
[email protected]bb88e1d32013-05-03 23:11:079209 session_deps_.socket_factory->AddSocketDataProvider(&data);
9210 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:579211
[email protected]49639fa2011-12-20 23:22:419212 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579213
[email protected]bb88e1d32013-05-03 23:11:079214 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:579215
mmenkee65e7af2015-10-13 17:16:429216 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579217 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419218 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579219
[email protected]49639fa2011-12-20 23:22:419220 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579221 EXPECT_EQ(ERR_IO_PENDING, rv);
9222
9223 rv = callback.WaitForResult();
9224 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
9225}
9226
[email protected]23e482282013-06-14 16:08:029227TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:469228 HttpRequestInfo request;
9229 request.method = "GET";
bncce36dca22015-04-21 22:11:239230 request.url = GURL("http://www.example.org/");
[email protected]9492e4a2010-02-24 00:58:469231 request.load_flags = 0;
9232
mmenkee65e7af2015-10-13 17:16:429233 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279234 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419235 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:279236
[email protected]e22e1362009-11-23 21:31:129237 MockRead data_reads[] = {
9238 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069239 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:129240 };
[email protected]9492e4a2010-02-24 00:58:469241
9242 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079243 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:469244
[email protected]49639fa2011-12-20 23:22:419245 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:469246
[email protected]49639fa2011-12-20 23:22:419247 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:469248 EXPECT_EQ(ERR_IO_PENDING, rv);
9249
9250 EXPECT_EQ(OK, callback.WaitForResult());
9251
9252 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509253 ASSERT_TRUE(response != NULL);
[email protected]9492e4a2010-02-24 00:58:469254
[email protected]90499482013-06-01 00:39:509255 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]9492e4a2010-02-24 00:58:469256 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9257
9258 std::string response_data;
9259 rv = ReadTransaction(trans.get(), &response_data);
[email protected]5543cbb2012-04-20 16:35:239260 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
[email protected]e22e1362009-11-23 21:31:129261}
9262
[email protected]23e482282013-06-14 16:08:029263TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:159264 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:529265 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:149266 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:219267 UploadFileElementReader::ScopedOverridingContentLengthForTests
9268 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:339269
olli.raula6df48b2a2015-11-26 07:40:229270 std::vector<scoped_ptr<UploadElementReader>> element_readers;
9271 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
avibf0746c2015-12-09 19:53:149272 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
9273 std::numeric_limits<uint64_t>::max(), base::Time())));
olli.raula6df48b2a2015-11-26 07:40:229274 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279275
9276 HttpRequestInfo request;
9277 request.method = "POST";
bncce36dca22015-04-21 22:11:239278 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279279 request.upload_data_stream = &upload_data_stream;
9280 request.load_flags = 0;
9281
mmenkee65e7af2015-10-13 17:16:429282 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]329b68b2012-11-14 17:54:279283 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419284 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]95d88ffe2010-02-04 21:25:339285
9286 MockRead data_reads[] = {
9287 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9288 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069289 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:339290 };
[email protected]31a2bfe2010-02-09 08:03:399291 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079292 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:339293
[email protected]49639fa2011-12-20 23:22:419294 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:339295
[email protected]49639fa2011-12-20 23:22:419296 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:339297 EXPECT_EQ(ERR_IO_PENDING, rv);
9298
9299 rv = callback.WaitForResult();
9300 EXPECT_EQ(OK, rv);
9301
9302 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509303 ASSERT_TRUE(response != NULL);
[email protected]95d88ffe2010-02-04 21:25:339304
[email protected]90499482013-06-01 00:39:509305 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]95d88ffe2010-02-04 21:25:339306 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9307
9308 std::string response_data;
9309 rv = ReadTransaction(trans.get(), &response_data);
9310 EXPECT_EQ(OK, rv);
9311 EXPECT_EQ("hello world", response_data);
9312
[email protected]dd3aa792013-07-16 19:10:239313 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:339314}
9315
[email protected]23e482282013-06-14 16:08:029316TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:159317 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:529318 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:369319 std::string temp_file_content("Unreadable file.");
[email protected]e5c2a22e2014-03-06 20:42:309320 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
[email protected]6624b4622010-03-29 19:58:369321 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:119322 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:369323
olli.raula6df48b2a2015-11-26 07:40:229324 std::vector<scoped_ptr<UploadElementReader>> element_readers;
avibf0746c2015-12-09 19:53:149325 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
9326 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
9327 std::numeric_limits<uint64_t>::max(), base::Time())));
olli.raula6df48b2a2015-11-26 07:40:229328 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279329
9330 HttpRequestInfo request;
9331 request.method = "POST";
bncce36dca22015-04-21 22:11:239332 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279333 request.upload_data_stream = &upload_data_stream;
9334 request.load_flags = 0;
9335
[email protected]999dd8c2013-11-12 06:45:549336 // If we try to upload an unreadable file, the transaction should fail.
mmenkee65e7af2015-10-13 17:16:429337 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]329b68b2012-11-14 17:54:279338 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419339 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]6624b4622010-03-29 19:58:369340
[email protected]999dd8c2013-11-12 06:45:549341 StaticSocketDataProvider data(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079342 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:369343
[email protected]49639fa2011-12-20 23:22:419344 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:369345
[email protected]49639fa2011-12-20 23:22:419346 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:369347 EXPECT_EQ(ERR_IO_PENDING, rv);
9348
9349 rv = callback.WaitForResult();
[email protected]999dd8c2013-11-12 06:45:549350 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
[email protected]6624b4622010-03-29 19:58:369351
[email protected]dd3aa792013-07-16 19:10:239352 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:369353}
9354
[email protected]02cad5d2013-10-02 08:14:039355TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
9356 class FakeUploadElementReader : public UploadElementReader {
9357 public:
9358 FakeUploadElementReader() {}
dchengb03027d2014-10-21 12:00:209359 ~FakeUploadElementReader() override {}
[email protected]02cad5d2013-10-02 08:14:039360
9361 const CompletionCallback& callback() const { return callback_; }
9362
9363 // UploadElementReader overrides:
dchengb03027d2014-10-21 12:00:209364 int Init(const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039365 callback_ = callback;
9366 return ERR_IO_PENDING;
9367 }
avibf0746c2015-12-09 19:53:149368 uint64_t GetContentLength() const override { return 0; }
9369 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:209370 int Read(IOBuffer* buf,
9371 int buf_length,
9372 const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039373 return ERR_FAILED;
9374 }
9375
9376 private:
9377 CompletionCallback callback_;
9378 };
9379
9380 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
olli.raula6df48b2a2015-11-26 07:40:229381 std::vector<scoped_ptr<UploadElementReader>> element_readers;
9382 element_readers.push_back(make_scoped_ptr(fake_reader));
9383 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:039384
9385 HttpRequestInfo request;
9386 request.method = "POST";
bncce36dca22015-04-21 22:11:239387 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:039388 request.upload_data_stream = &upload_data_stream;
9389 request.load_flags = 0;
9390
mmenkee65e7af2015-10-13 17:16:429391 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02cad5d2013-10-02 08:14:039392 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419393 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02cad5d2013-10-02 08:14:039394
9395 StaticSocketDataProvider data;
9396 session_deps_.socket_factory->AddSocketDataProvider(&data);
9397
9398 TestCompletionCallback callback;
9399 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9400 EXPECT_EQ(ERR_IO_PENDING, rv);
9401 base::MessageLoop::current()->RunUntilIdle();
9402
9403 // Transaction is pending on request body initialization.
9404 ASSERT_FALSE(fake_reader->callback().is_null());
9405
9406 // Return Init()'s result after the transaction gets destroyed.
9407 trans.reset();
9408 fake_reader->callback().Run(OK); // Should not crash.
9409}
9410
[email protected]aeefc9e82010-02-19 16:18:279411// Tests that changes to Auth realms are treated like auth rejections.
[email protected]23e482282013-06-14 16:08:029412TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:279413 HttpRequestInfo request;
9414 request.method = "GET";
bncce36dca22015-04-21 22:11:239415 request.url = GURL("http://www.example.org/");
[email protected]aeefc9e82010-02-19 16:18:279416 request.load_flags = 0;
9417
9418 // First transaction will request a resource and receive a Basic challenge
9419 // with realm="first_realm".
9420 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239421 MockWrite(
9422 "GET / HTTP/1.1\r\n"
9423 "Host: www.example.org\r\n"
9424 "Connection: keep-alive\r\n"
9425 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279426 };
9427 MockRead data_reads1[] = {
9428 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9429 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9430 "\r\n"),
9431 };
9432
9433 // After calling trans->RestartWithAuth(), provide an Authentication header
9434 // for first_realm. The server will reject and provide a challenge with
9435 // second_realm.
9436 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239437 MockWrite(
9438 "GET / HTTP/1.1\r\n"
9439 "Host: www.example.org\r\n"
9440 "Connection: keep-alive\r\n"
9441 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
9442 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279443 };
9444 MockRead data_reads2[] = {
9445 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9446 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
9447 "\r\n"),
9448 };
9449
9450 // This again fails, and goes back to first_realm. Make sure that the
9451 // entry is removed from cache.
9452 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239453 MockWrite(
9454 "GET / HTTP/1.1\r\n"
9455 "Host: www.example.org\r\n"
9456 "Connection: keep-alive\r\n"
9457 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
9458 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279459 };
9460 MockRead data_reads3[] = {
9461 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9462 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9463 "\r\n"),
9464 };
9465
9466 // Try one last time (with the correct password) and get the resource.
9467 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:239468 MockWrite(
9469 "GET / HTTP/1.1\r\n"
9470 "Host: www.example.org\r\n"
9471 "Connection: keep-alive\r\n"
9472 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
9473 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279474 };
9475 MockRead data_reads4[] = {
9476 MockRead("HTTP/1.1 200 OK\r\n"
9477 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:509478 "Content-Length: 5\r\n"
9479 "\r\n"
9480 "hello"),
[email protected]aeefc9e82010-02-19 16:18:279481 };
9482
9483 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9484 data_writes1, arraysize(data_writes1));
9485 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9486 data_writes2, arraysize(data_writes2));
9487 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
9488 data_writes3, arraysize(data_writes3));
9489 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
9490 data_writes4, arraysize(data_writes4));
[email protected]bb88e1d32013-05-03 23:11:079491 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9492 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9493 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9494 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:279495
[email protected]49639fa2011-12-20 23:22:419496 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:279497
mmenkee65e7af2015-10-13 17:16:429498 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0b0bf032010-09-21 18:08:509499 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419500 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509501
[email protected]aeefc9e82010-02-19 16:18:279502 // Issue the first request with Authorize headers. There should be a
9503 // password prompt for first_realm waiting to be filled in after the
9504 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419505 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:279506 EXPECT_EQ(ERR_IO_PENDING, rv);
9507 rv = callback1.WaitForResult();
9508 EXPECT_EQ(OK, rv);
9509 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509510 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049511 const AuthChallengeInfo* challenge = response->auth_challenge.get();
9512 ASSERT_FALSE(challenge == NULL);
9513 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239514 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049515 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199516 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279517
9518 // Issue the second request with an incorrect password. There should be a
9519 // password prompt for second_realm waiting to be filled in after the
9520 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419521 TestCompletionCallback callback2;
9522 rv = trans->RestartWithAuth(
9523 AuthCredentials(kFirst, kBaz), callback2.callback());
[email protected]aeefc9e82010-02-19 16:18:279524 EXPECT_EQ(ERR_IO_PENDING, rv);
9525 rv = callback2.WaitForResult();
9526 EXPECT_EQ(OK, rv);
9527 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509528 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049529 challenge = response->auth_challenge.get();
9530 ASSERT_FALSE(challenge == NULL);
9531 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239532 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049533 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199534 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279535
9536 // Issue the third request with another incorrect password. There should be
9537 // a password prompt for first_realm waiting to be filled in. If the password
9538 // prompt is not present, it indicates that the HttpAuthCacheEntry for
9539 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:419540 TestCompletionCallback callback3;
9541 rv = trans->RestartWithAuth(
9542 AuthCredentials(kSecond, kFou), callback3.callback());
[email protected]aeefc9e82010-02-19 16:18:279543 EXPECT_EQ(ERR_IO_PENDING, rv);
9544 rv = callback3.WaitForResult();
9545 EXPECT_EQ(OK, rv);
9546 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509547 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049548 challenge = response->auth_challenge.get();
9549 ASSERT_FALSE(challenge == NULL);
9550 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239551 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049552 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199553 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279554
9555 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:419556 TestCompletionCallback callback4;
9557 rv = trans->RestartWithAuth(
9558 AuthCredentials(kFirst, kBar), callback4.callback());
[email protected]aeefc9e82010-02-19 16:18:279559 EXPECT_EQ(ERR_IO_PENDING, rv);
9560 rv = callback4.WaitForResult();
9561 EXPECT_EQ(OK, rv);
9562 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509563 ASSERT_TRUE(response != NULL);
[email protected]aeefc9e82010-02-19 16:18:279564 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9565}
9566
bncc958faa2015-07-31 18:14:529567TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
9568 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359569 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529570
9571 std::string alternative_service_http_header =
9572 GetAlternativeServiceHttpHeader();
9573
9574 MockRead data_reads[] = {
9575 MockRead("HTTP/1.1 200 OK\r\n"),
9576 MockRead(alternative_service_http_header.c_str()),
9577 MockRead("\r\n"),
9578 MockRead("hello world"),
9579 MockRead(SYNCHRONOUS, OK),
9580 };
9581
9582 HttpRequestInfo request;
9583 request.method = "GET";
9584 request.url = GURL("http://www.example.org/");
9585 request.load_flags = 0;
9586
9587 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9588
9589 session_deps_.socket_factory->AddSocketDataProvider(&data);
9590
9591 TestCompletionCallback callback;
9592
mmenkee65e7af2015-10-13 17:16:429593 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529594 scoped_ptr<HttpTransaction> trans(
9595 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9596
9597 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9598 EXPECT_EQ(ERR_IO_PENDING, rv);
9599
9600 HostPortPair http_host_port_pair("www.example.org", 80);
9601 HttpServerProperties& http_server_properties =
9602 *session->http_server_properties();
9603 AlternativeServiceVector alternative_service_vector =
9604 http_server_properties.GetAlternativeServices(http_host_port_pair);
9605 EXPECT_TRUE(alternative_service_vector.empty());
9606
9607 EXPECT_EQ(OK, callback.WaitForResult());
9608
9609 const HttpResponseInfo* response = trans->GetResponseInfo();
9610 ASSERT_TRUE(response != NULL);
9611 ASSERT_TRUE(response->headers.get() != NULL);
9612 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9613 EXPECT_FALSE(response->was_fetched_via_spdy);
9614 EXPECT_FALSE(response->was_npn_negotiated);
9615
9616 std::string response_data;
9617 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9618 EXPECT_EQ("hello world", response_data);
9619
9620 alternative_service_vector =
9621 http_server_properties.GetAlternativeServices(http_host_port_pair);
9622 ASSERT_EQ(1u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389623 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529624 alternative_service_vector[0].protocol);
9625 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9626 EXPECT_EQ(443, alternative_service_vector[0].port);
9627}
9628
bnc4f575852015-10-14 18:35:089629TEST_P(HttpNetworkTransactionTest, ClearAlternativeServices) {
9630 session_deps_.next_protos = SpdyNextProtos();
9631 session_deps_.use_alternative_services = true;
9632
9633 // Set an alternative service for origin.
9634 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9635 HttpServerProperties& http_server_properties =
9636 *session->http_server_properties();
9637 HostPortPair http_host_port_pair("www.example.org", 80);
9638 AlternativeService alternative_service(QUIC, "", 80);
9639 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9640 http_server_properties.SetAlternativeService(
9641 http_host_port_pair, alternative_service, 1.0, expiration);
9642 AlternativeServiceVector alternative_service_vector =
9643 http_server_properties.GetAlternativeServices(http_host_port_pair);
9644 EXPECT_EQ(1u, alternative_service_vector.size());
9645
9646 // Send a clear header.
9647 MockRead data_reads[] = {
9648 MockRead("HTTP/1.1 200 OK\r\n"),
9649 MockRead("Alt-Svc: clear\r\n"),
9650 MockRead("\r\n"),
9651 MockRead("hello world"),
9652 MockRead(SYNCHRONOUS, OK),
9653 };
9654 StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
9655 session_deps_.socket_factory->AddSocketDataProvider(&data);
9656
9657 HttpRequestInfo request;
9658 request.method = "GET";
9659 request.url = GURL("http://www.example.org/");
9660 request.load_flags = 0;
9661
9662 TestCompletionCallback callback;
9663
9664 scoped_ptr<HttpTransaction> trans(
9665 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9666
9667 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9668 EXPECT_EQ(OK, callback.GetResult(rv));
9669
9670 const HttpResponseInfo* response = trans->GetResponseInfo();
9671 ASSERT_TRUE(response != nullptr);
9672 ASSERT_TRUE(response->headers.get() != nullptr);
9673 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9674 EXPECT_FALSE(response->was_fetched_via_spdy);
9675 EXPECT_FALSE(response->was_npn_negotiated);
9676
9677 std::string response_data;
9678 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9679 EXPECT_EQ("hello world", response_data);
9680
9681 alternative_service_vector =
9682 http_server_properties.GetAlternativeServices(http_host_port_pair);
9683 EXPECT_TRUE(alternative_service_vector.empty());
9684}
9685
bnc54ec34b72015-08-26 19:34:569686// Alternative Service headers must be ignored when |use_alternative_services|
9687// is false.
9688TEST_P(HttpNetworkTransactionTest, DoNotHonorAlternativeServiceHeader) {
9689 session_deps_.next_protos = SpdyNextProtos();
9690 session_deps_.use_alternative_services = false;
9691
9692 std::string alternative_service_http_header =
9693 GetAlternativeServiceHttpHeader();
9694
9695 MockRead data_reads[] = {
9696 MockRead("HTTP/1.1 200 OK\r\n"),
9697 MockRead(alternative_service_http_header.c_str()),
9698 MockRead("\r\n"),
9699 MockRead("hello world"),
9700 MockRead(SYNCHRONOUS, OK),
9701 };
9702
9703 HttpRequestInfo request;
9704 request.method = "GET";
9705 request.url = GURL("http://www.example.org/");
9706 request.load_flags = 0;
9707
9708 StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
9709
9710 session_deps_.socket_factory->AddSocketDataProvider(&data);
9711
9712 TestCompletionCallback callback;
9713
mmenkee65e7af2015-10-13 17:16:429714 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc54ec34b72015-08-26 19:34:569715 scoped_ptr<HttpTransaction> trans(
9716 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9717
9718 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9719 EXPECT_EQ(ERR_IO_PENDING, rv);
9720
9721 HostPortPair http_host_port_pair("www.example.org", 80);
9722 HttpServerProperties& http_server_properties =
9723 *session->http_server_properties();
9724 AlternativeServiceVector alternative_service_vector =
9725 http_server_properties.GetAlternativeServices(http_host_port_pair);
9726 EXPECT_TRUE(alternative_service_vector.empty());
9727
9728 EXPECT_EQ(OK, callback.WaitForResult());
9729
9730 const HttpResponseInfo* response = trans->GetResponseInfo();
9731 ASSERT_TRUE(response != nullptr);
9732 ASSERT_TRUE(response->headers.get() != nullptr);
9733 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9734 EXPECT_FALSE(response->was_fetched_via_spdy);
9735 EXPECT_FALSE(response->was_npn_negotiated);
9736
9737 std::string response_data;
9738 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9739 EXPECT_EQ("hello world", response_data);
9740
9741 alternative_service_vector =
9742 http_server_properties.GetAlternativeServices(http_host_port_pair);
9743 EXPECT_TRUE(alternative_service_vector.empty());
9744}
9745
bncc958faa2015-07-31 18:14:529746TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) {
9747 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359748 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529749
9750 MockRead data_reads[] = {
9751 MockRead("HTTP/1.1 200 OK\r\n"),
9752 MockRead("Alt-Svc: "),
9753 MockRead(GetAlternateProtocolFromParam()),
bnc44858c82015-10-16 11:57:219754 MockRead("=\"www.example.com:443\";p=\"1.0\","),
bncc958faa2015-07-31 18:14:529755 MockRead("quic=\":1234\"\r\n\r\n"),
9756 MockRead("hello world"),
9757 MockRead(SYNCHRONOUS, OK),
9758 };
9759
9760 HttpRequestInfo request;
9761 request.method = "GET";
9762 request.url = GURL("http://www.example.org/");
9763 request.load_flags = 0;
9764
9765 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9766
9767 session_deps_.socket_factory->AddSocketDataProvider(&data);
9768
9769 TestCompletionCallback callback;
9770
mmenkee65e7af2015-10-13 17:16:429771 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529772 scoped_ptr<HttpTransaction> trans(
9773 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9774
9775 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9776 EXPECT_EQ(ERR_IO_PENDING, rv);
9777
9778 HostPortPair http_host_port_pair("www.example.org", 80);
9779 HttpServerProperties& http_server_properties =
9780 *session->http_server_properties();
9781 AlternativeServiceVector alternative_service_vector =
9782 http_server_properties.GetAlternativeServices(http_host_port_pair);
9783 EXPECT_TRUE(alternative_service_vector.empty());
9784
9785 EXPECT_EQ(OK, callback.WaitForResult());
9786
9787 const HttpResponseInfo* response = trans->GetResponseInfo();
9788 ASSERT_TRUE(response != NULL);
9789 ASSERT_TRUE(response->headers.get() != NULL);
9790 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9791 EXPECT_FALSE(response->was_fetched_via_spdy);
9792 EXPECT_FALSE(response->was_npn_negotiated);
9793
9794 std::string response_data;
9795 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9796 EXPECT_EQ("hello world", response_data);
9797
9798 alternative_service_vector =
9799 http_server_properties.GetAlternativeServices(http_host_port_pair);
9800 ASSERT_EQ(2u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389801 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529802 alternative_service_vector[0].protocol);
9803 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9804 EXPECT_EQ(443, alternative_service_vector[0].port);
9805 EXPECT_EQ(QUIC, alternative_service_vector[1].protocol);
9806 EXPECT_EQ("www.example.org", alternative_service_vector[1].host);
9807 EXPECT_EQ(1234, alternative_service_vector[1].port);
9808}
9809
bnc54ec34b72015-08-26 19:34:569810// Alternate Protocol headers must be honored even if |use_alternative_services|
9811// is false.
[email protected]23e482282013-06-14 16:08:029812TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]d7599122014-05-24 03:37:239813 session_deps_.next_protos = SpdyNextProtos();
bnc54ec34b72015-08-26 19:34:569814 session_deps_.use_alternative_services = false;
[email protected]a2cb8122010-03-10 17:22:429815
[email protected]8a0fc822013-06-27 20:52:439816 std::string alternate_protocol_http_header =
9817 GetAlternateProtocolHttpHeader();
9818
[email protected]564b4912010-03-09 16:30:429819 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:529820 MockRead("HTTP/1.1 200 OK\r\n"),
9821 MockRead(alternate_protocol_http_header.c_str()),
9822 MockRead("\r\n"),
9823 MockRead("hello world"),
9824 MockRead(SYNCHRONOUS, OK),
[email protected]564b4912010-03-09 16:30:429825 };
9826
9827 HttpRequestInfo request;
9828 request.method = "GET";
bncce36dca22015-04-21 22:11:239829 request.url = GURL("http://www.example.org/");
[email protected]564b4912010-03-09 16:30:429830 request.load_flags = 0;
9831
9832 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9833
[email protected]bb88e1d32013-05-03 23:11:079834 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]564b4912010-03-09 16:30:429835
[email protected]49639fa2011-12-20 23:22:419836 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:429837
mmenkee65e7af2015-10-13 17:16:429838 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:369839 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509840 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]564b4912010-03-09 16:30:429841
[email protected]49639fa2011-12-20 23:22:419842 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:429843 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:539844
bncce36dca22015-04-21 22:11:239845 HostPortPair http_host_port_pair("www.example.org", 80);
[email protected]9801e3702014-03-07 09:33:559846 HttpServerProperties& http_server_properties =
[email protected]17291a022011-10-10 07:32:539847 *session->http_server_properties();
bncd9b132e2015-07-08 05:16:109848 AlternativeServiceVector alternative_service_vector =
9849 http_server_properties.GetAlternativeServices(http_host_port_pair);
9850 EXPECT_TRUE(alternative_service_vector.empty());
[email protected]564b4912010-03-09 16:30:429851
9852 EXPECT_EQ(OK, callback.WaitForResult());
9853
9854 const HttpResponseInfo* response = trans->GetResponseInfo();
9855 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:509856 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]564b4912010-03-09 16:30:429857 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:539858 EXPECT_FALSE(response->was_fetched_via_spdy);
9859 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:429860
9861 std::string response_data;
9862 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9863 EXPECT_EQ("hello world", response_data);
9864
bncd9b132e2015-07-08 05:16:109865 alternative_service_vector =
9866 http_server_properties.GetAlternativeServices(http_host_port_pair);
9867 ASSERT_EQ(1u, alternative_service_vector.size());
9868 EXPECT_EQ(443, alternative_service_vector[0].port);
rdsmithebb50aa2015-11-12 03:44:389869 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncd9b132e2015-07-08 05:16:109870 alternative_service_vector[0].protocol);
[email protected]564b4912010-03-09 16:30:429871}
9872
rch89c6e102015-03-18 18:56:529873TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
9874 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359875 session_deps_.use_alternative_services = true;
rch89c6e102015-03-18 18:56:529876
9877 MockRead data_reads[] = {
9878 MockRead("HTTP/1.1 200 OK\r\n"),
9879 MockRead("Alternate-Protocol: \r\n\r\n"),
9880 MockRead("hello world"),
9881 MockRead(SYNCHRONOUS, OK),
9882 };
9883
9884 HttpRequestInfo request;
9885 request.method = "GET";
bncce36dca22015-04-21 22:11:239886 request.url = GURL("http://www.example.org/");
rch89c6e102015-03-18 18:56:529887 request.load_flags = 0;
9888
9889 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9890
9891 session_deps_.socket_factory->AddSocketDataProvider(&data);
9892
9893 TestCompletionCallback callback;
9894
mmenkee65e7af2015-10-13 17:16:429895 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rch89c6e102015-03-18 18:56:529896
bncce36dca22015-04-21 22:11:239897 HostPortPair http_host_port_pair("www.example.org", 80);
rch89c6e102015-03-18 18:56:529898 HttpServerProperties& http_server_properties =
9899 *session->http_server_properties();
bnccacc0992015-03-20 20:22:229900 AlternativeService alternative_service(QUIC, "", 80);
bnc7dc7e1b42015-07-28 14:43:129901 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9902 http_server_properties.SetAlternativeService(
9903 http_host_port_pair, alternative_service, 1.0, expiration);
bnccacc0992015-03-20 20:22:229904
bncd9b132e2015-07-08 05:16:109905 AlternativeServiceVector alternative_service_vector =
9906 http_server_properties.GetAlternativeServices(http_host_port_pair);
9907 ASSERT_EQ(1u, alternative_service_vector.size());
9908 EXPECT_EQ(QUIC, alternative_service_vector[0].protocol);
rch89c6e102015-03-18 18:56:529909
9910 scoped_ptr<HttpTransaction> trans(
9911 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9912
9913 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9914 EXPECT_EQ(ERR_IO_PENDING, rv);
9915
9916 EXPECT_EQ(OK, callback.WaitForResult());
9917
9918 const HttpResponseInfo* response = trans->GetResponseInfo();
9919 ASSERT_TRUE(response != NULL);
9920 ASSERT_TRUE(response->headers.get() != NULL);
9921 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9922 EXPECT_FALSE(response->was_fetched_via_spdy);
9923 EXPECT_FALSE(response->was_npn_negotiated);
9924
9925 std::string response_data;
9926 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9927 EXPECT_EQ("hello world", response_data);
9928
bncd9b132e2015-07-08 05:16:109929 alternative_service_vector =
9930 http_server_properties.GetAlternativeServices(http_host_port_pair);
9931 EXPECT_TRUE(alternative_service_vector.empty());
rch89c6e102015-03-18 18:56:529932}
9933
bncc958faa2015-07-31 18:14:529934TEST_P(HttpNetworkTransactionTest, AltSvcOverwritesAlternateProtocol) {
9935 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359936 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529937
9938 std::string alternative_service_http_header =
9939 GetAlternativeServiceHttpHeader();
9940 std::string alternate_protocol_http_header = GetAlternateProtocolHttpHeader();
9941
9942 MockRead data_reads[] = {
9943 MockRead("HTTP/1.1 200 OK\r\n"),
9944 MockRead(alternative_service_http_header.c_str()),
9945 MockRead(alternate_protocol_http_header.c_str()),
9946 MockRead("\r\n"),
9947 MockRead("hello world"),
9948 MockRead(SYNCHRONOUS, OK),
9949 };
9950
9951 HttpRequestInfo request;
9952 request.method = "GET";
9953 request.url = GURL("http://www.example.org/");
9954 request.load_flags = 0;
9955
9956 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9957
9958 session_deps_.socket_factory->AddSocketDataProvider(&data);
9959
9960 TestCompletionCallback callback;
9961
mmenkee65e7af2015-10-13 17:16:429962 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529963 scoped_ptr<HttpTransaction> trans(
9964 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9965
9966 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9967 EXPECT_EQ(ERR_IO_PENDING, rv);
9968
9969 HostPortPair http_host_port_pair("www.example.org", 80);
9970 HttpServerProperties& http_server_properties =
9971 *session->http_server_properties();
9972 AlternativeServiceVector alternative_service_vector =
9973 http_server_properties.GetAlternativeServices(http_host_port_pair);
9974 EXPECT_TRUE(alternative_service_vector.empty());
9975
9976 EXPECT_EQ(OK, callback.WaitForResult());
9977
9978 const HttpResponseInfo* response = trans->GetResponseInfo();
9979 ASSERT_TRUE(response != NULL);
9980 ASSERT_TRUE(response->headers.get() != NULL);
9981 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9982 EXPECT_FALSE(response->was_fetched_via_spdy);
9983 EXPECT_FALSE(response->was_npn_negotiated);
9984
9985 std::string response_data;
9986 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9987 EXPECT_EQ("hello world", response_data);
9988
9989 alternative_service_vector =
9990 http_server_properties.GetAlternativeServices(http_host_port_pair);
9991 ASSERT_EQ(1u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389992 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529993 alternative_service_vector[0].protocol);
9994 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9995 EXPECT_EQ(443, alternative_service_vector[0].port);
9996}
9997
bnc54ec34b72015-08-26 19:34:569998// When |use_alternative_services| is false, do not observe alternative service
9999// entries that point to a different host.
10000TEST_P(HttpNetworkTransactionTest, DisableAlternativeServiceToDifferentHost) {
10001 session_deps_.use_alternative_services = false;
10002
10003 HttpRequestInfo request;
10004 request.method = "GET";
10005 request.url = GURL("http://www.example.org/");
10006 request.load_flags = 0;
10007
10008 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
10009 StaticSocketDataProvider first_data;
10010 first_data.set_connect_data(mock_connect);
10011 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
10012
10013 MockRead data_reads[] = {
10014 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
10015 MockRead(ASYNC, OK),
10016 };
10017 StaticSocketDataProvider second_data(data_reads, arraysize(data_reads),
10018 nullptr, 0);
10019 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
10020
mmenkee65e7af2015-10-13 17:16:4210021 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc54ec34b72015-08-26 19:34:5610022
10023 base::WeakPtr<HttpServerProperties> http_server_properties =
10024 session->http_server_properties();
10025 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810026 AlternateProtocolFromNextProto(GetProtocol()), "different.example.org",
10027 80);
bnc54ec34b72015-08-26 19:34:5610028 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10029 http_server_properties->SetAlternativeService(
10030 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
10031
10032 scoped_ptr<HttpTransaction> trans(
10033 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10034 TestCompletionCallback callback;
10035
10036 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10037 // The connetion to origin was refused, and the alternative service should not
10038 // be used (even though mock data are there), therefore the request should
10039 // fail.
10040 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.GetResult(rv));
10041}
10042
zhongyi48704c182015-12-07 07:52:0210043TEST_P(HttpNetworkTransactionTest, IdentifyQuicBroken) {
10044 HostPortPair origin("origin.example.org", 443);
10045 HostPortPair alternative("alternative.example.org", 443);
10046 std::string origin_url = "https://origin.example.org:443";
10047 std::string alternative_url = "https://alternative.example.org:443";
10048
10049 // Negotiate HTTP/1.1 with alternative.example.org.
10050 SSLSocketDataProvider ssl(ASYNC, OK);
10051 ssl.SetNextProto(kProtoHTTP11);
10052 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10053
10054 // HTTP/1.1 data for request.
10055 MockWrite http_writes[] = {
10056 MockWrite("GET / HTTP/1.1\r\n"
10057 "Host: alternative.example.org\r\n"
10058 "Connection: keep-alive\r\n\r\n"),
10059 };
10060
10061 MockRead http_reads[] = {
10062 MockRead("HTTP/1.1 200 OK\r\n"
10063 "Content-Type: text/html; charset=iso-8859-1\r\n"
10064 "Content-Length: 40\r\n\r\n"
10065 "first HTTP/1.1 response from alternative"),
10066 };
10067 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
10068 http_writes, arraysize(http_writes));
10069 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
10070
10071 StaticSocketDataProvider data_refused;
10072 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
10073 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
10074
10075 // Set up a QUIC alternative service for origin.
10076 session_deps_.use_alternative_services = true;
10077 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10078 base::WeakPtr<HttpServerProperties> http_server_properties =
10079 session->http_server_properties();
10080 AlternativeService alternative_service(QUIC, alternative);
10081 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10082 http_server_properties->SetAlternativeService(origin, alternative_service,
10083 1.0, expiration);
10084 // Mark the QUIC alternative service as broken.
10085 http_server_properties->MarkAlternativeServiceBroken(alternative_service);
10086
10087 scoped_ptr<HttpTransaction> trans(
10088 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10089 HttpRequestInfo request;
10090 request.method = "GET";
10091 request.url = GURL(origin_url);
10092 request.load_flags = 0;
10093 TestCompletionCallback callback;
10094 NetErrorDetails details;
10095 EXPECT_FALSE(details.quic_broken);
10096
10097 trans->Start(&request, callback.callback(), BoundNetLog());
10098 trans->PopulateNetErrorDetails(&details);
10099 EXPECT_TRUE(details.quic_broken);
10100}
10101
10102TEST_P(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
10103 HostPortPair origin("origin.example.org", 443);
10104 HostPortPair alternative1("alternative1.example.org", 443);
10105 HostPortPair alternative2("alternative2.example.org", 443);
10106 std::string origin_url = "https://origin.example.org:443";
10107 std::string alternative_url1 = "https://alternative1.example.org:443";
10108 std::string alternative_url2 = "https://alternative2.example.org:443";
10109
10110 // Negotiate HTTP/1.1 with alternative1.example.org.
10111 SSLSocketDataProvider ssl(ASYNC, OK);
10112 ssl.SetNextProto(kProtoHTTP11);
10113 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10114
10115 // HTTP/1.1 data for request.
10116 MockWrite http_writes[] = {
10117 MockWrite("GET / HTTP/1.1\r\n"
10118 "Host: alternative1.example.org\r\n"
10119 "Connection: keep-alive\r\n\r\n"),
10120 };
10121
10122 MockRead http_reads[] = {
10123 MockRead("HTTP/1.1 200 OK\r\n"
10124 "Content-Type: text/html; charset=iso-8859-1\r\n"
10125 "Content-Length: 40\r\n\r\n"
10126 "first HTTP/1.1 response from alternative1"),
10127 };
10128 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
10129 http_writes, arraysize(http_writes));
10130 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
10131
10132 StaticSocketDataProvider data_refused;
10133 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
10134 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
10135
10136 session_deps_.use_alternative_services = true;
10137 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10138 base::WeakPtr<HttpServerProperties> http_server_properties =
10139 session->http_server_properties();
10140
10141 // Set up two QUIC alternative services for origin.
10142 AlternativeServiceInfoVector alternative_service_info_vector;
10143 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10144
10145 AlternativeService alternative_service1(QUIC, alternative1);
10146 AlternativeServiceInfo alternative_service_info1(alternative_service1, 1.0,
10147 expiration);
10148 alternative_service_info_vector.push_back(alternative_service_info1);
10149 AlternativeService alternative_service2(QUIC, alternative2);
10150 AlternativeServiceInfo alternative_service_info2(alternative_service2, 1.0,
10151 expiration);
10152 alternative_service_info_vector.push_back(alternative_service_info2);
10153
10154 http_server_properties->SetAlternativeServices(
10155 origin, alternative_service_info_vector);
10156
10157 // Mark one of the QUIC alternative service as broken.
10158 http_server_properties->MarkAlternativeServiceBroken(alternative_service1);
10159
10160 const AlternativeServiceVector alternative_service_vector =
10161 http_server_properties->GetAlternativeServices(origin);
10162
10163 scoped_ptr<HttpTransaction> trans(
10164 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10165 HttpRequestInfo request;
10166 request.method = "GET";
10167 request.url = GURL(origin_url);
10168 request.load_flags = 0;
10169 TestCompletionCallback callback;
10170 NetErrorDetails details;
10171 EXPECT_FALSE(details.quic_broken);
10172
10173 trans->Start(&request, callback.callback(), BoundNetLog());
10174 trans->PopulateNetErrorDetails(&details);
10175 EXPECT_FALSE(details.quic_broken);
10176}
10177
[email protected]23e482282013-06-14 16:08:0210178TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310179 MarkBrokenAlternateProtocolAndFallback) {
bnc55ff9da2015-08-19 18:42:3510180 session_deps_.use_alternative_services = true;
[email protected]564b4912010-03-09 16:30:4210181
10182 HttpRequestInfo request;
10183 request.method = "GET";
bncce36dca22015-04-21 22:11:2310184 request.url = GURL("http://www.example.org/");
[email protected]564b4912010-03-09 16:30:4210185 request.load_flags = 0;
10186
[email protected]d973e99a2012-02-17 21:02:3610187 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4210188 StaticSocketDataProvider first_data;
10189 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710190 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]564b4912010-03-09 16:30:4210191
10192 MockRead data_reads[] = {
10193 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10194 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610195 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4210196 };
10197 StaticSocketDataProvider second_data(
10198 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710199 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4210200
mmenkee65e7af2015-10-13 17:16:4210201 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4210202
[email protected]30d4c022013-07-18 22:58:1610203 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310204 session->http_server_properties();
bnc8445b3002015-03-13 01:57:0910205 const HostPortPair host_port_pair = HostPortPair::FromURL(request.url);
[email protected]3912662a32011-10-04 00:51:1110206 // Port must be < 1024, or the header will be ignored (since initial port was
10207 // port 80 (another restricted port).
bncd9b132e2015-07-08 05:16:1010208 const AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810209 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bncd9b132e2015-07-08 05:16:1010210 666); // Port is ignored by MockConnect anyway.
bnc7dc7e1b42015-07-28 14:43:1210211 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10212 http_server_properties->SetAlternativeService(
10213 host_port_pair, alternative_service, 1.0, expiration);
[email protected]564b4912010-03-09 16:30:4210214
[email protected]262eec82013-03-19 21:01:3610215 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010216 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110217 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4210218
[email protected]49639fa2011-12-20 23:22:4110219 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:4210220 EXPECT_EQ(ERR_IO_PENDING, rv);
10221 EXPECT_EQ(OK, callback.WaitForResult());
10222
10223 const HttpResponseInfo* response = trans->GetResponseInfo();
10224 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010225 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]564b4912010-03-09 16:30:4210226 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10227
10228 std::string response_data;
10229 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10230 EXPECT_EQ("hello world", response_data);
10231
bncd9b132e2015-07-08 05:16:1010232 const AlternativeServiceVector alternative_service_vector =
10233 http_server_properties->GetAlternativeServices(host_port_pair);
10234 ASSERT_EQ(1u, alternative_service_vector.size());
10235 EXPECT_EQ(alternative_service, alternative_service_vector[0]);
10236 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
10237 alternative_service_vector[0]));
[email protected]564b4912010-03-09 16:30:4210238}
10239
bnc55ff9da2015-08-19 18:42:3510240// Ensure that we are not allowed to redirect traffic via an alternate protocol
10241// to an unrestricted (port >= 1024) when the original traffic was on a
10242// restricted port (port < 1024). Ensure that we can redirect in all other
10243// cases.
[email protected]23e482282013-06-14 16:08:0210244TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310245 AlternateProtocolPortRestrictedBlocked) {
bnc55ff9da2015-08-19 18:42:3510246 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110247
10248 HttpRequestInfo restricted_port_request;
10249 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310250 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1110251 restricted_port_request.load_flags = 0;
10252
[email protected]d973e99a2012-02-17 21:02:3610253 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110254 StaticSocketDataProvider first_data;
10255 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710256 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110257
10258 MockRead data_reads[] = {
10259 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10260 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610261 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110262 };
10263 StaticSocketDataProvider second_data(
10264 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710265 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110266
mmenkee65e7af2015-10-13 17:16:4210267 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110268
[email protected]30d4c022013-07-18 22:58:1610269 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310270 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110271 const int kUnrestrictedAlternatePort = 1024;
bnccacc0992015-03-20 20:22:2210272 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810273 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210274 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210275 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210276 http_server_properties->SetAlternativeService(
10277 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210278 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110279
[email protected]262eec82013-03-19 21:01:3610280 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010281 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110282 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110283
[email protected]49639fa2011-12-20 23:22:4110284 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:3610285 &restricted_port_request,
10286 callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110287 EXPECT_EQ(ERR_IO_PENDING, rv);
10288 // Invalid change to unrestricted port should fail.
10289 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
[email protected]c54c6962013-02-01 04:53:1910290}
[email protected]3912662a32011-10-04 00:51:1110291
bnc55ff9da2015-08-19 18:42:3510292// Ensure that we are allowed to redirect traffic via an alternate protocol to
10293// an unrestricted (port >= 1024) when the original traffic was on a restricted
10294// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
[email protected]23e482282013-06-14 16:08:0210295TEST_P(HttpNetworkTransactionTest,
[email protected]c54c6962013-02-01 04:53:1910296 AlternateProtocolPortRestrictedPermitted) {
bnc55ff9da2015-08-19 18:42:3510297 session_deps_.use_alternative_services = true;
[email protected]bb88e1d32013-05-03 23:11:0710298 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1910299
10300 HttpRequestInfo restricted_port_request;
10301 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310302 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1910303 restricted_port_request.load_flags = 0;
10304
10305 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
10306 StaticSocketDataProvider first_data;
10307 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710308 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1910309
10310 MockRead data_reads[] = {
10311 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10312 MockRead("hello world"),
10313 MockRead(ASYNC, OK),
10314 };
10315 StaticSocketDataProvider second_data(
10316 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710317 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]c54c6962013-02-01 04:53:1910318
mmenkee65e7af2015-10-13 17:16:4210319 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1910320
[email protected]30d4c022013-07-18 22:58:1610321 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]c54c6962013-02-01 04:53:1910322 session->http_server_properties();
10323 const int kUnrestrictedAlternatePort = 1024;
bnccacc0992015-03-20 20:22:2210324 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810325 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210326 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210327 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210328 http_server_properties->SetAlternativeService(
10329 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210330 1.0, expiration);
[email protected]c54c6962013-02-01 04:53:1910331
[email protected]262eec82013-03-19 21:01:3610332 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010333 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]c54c6962013-02-01 04:53:1910334 TestCompletionCallback callback;
10335
10336 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
[email protected]262eec82013-03-19 21:01:3610337 &restricted_port_request,
10338 callback.callback(), BoundNetLog()));
[email protected]c54c6962013-02-01 04:53:1910339 // Change to unrestricted port should succeed.
10340 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110341}
10342
bnc55ff9da2015-08-19 18:42:3510343// Ensure that we are not allowed to redirect traffic via an alternate protocol
10344// to an unrestricted (port >= 1024) when the original traffic was on a
10345// restricted port (port < 1024). Ensure that we can redirect in all other
10346// cases.
[email protected]23e482282013-06-14 16:08:0210347TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310348 AlternateProtocolPortRestrictedAllowed) {
bnc55ff9da2015-08-19 18:42:3510349 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110350
10351 HttpRequestInfo restricted_port_request;
10352 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310353 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1110354 restricted_port_request.load_flags = 0;
10355
[email protected]d973e99a2012-02-17 21:02:3610356 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110357 StaticSocketDataProvider first_data;
10358 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710359 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110360
10361 MockRead data_reads[] = {
10362 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10363 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610364 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110365 };
10366 StaticSocketDataProvider second_data(
10367 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710368 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110369
mmenkee65e7af2015-10-13 17:16:4210370 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110371
[email protected]30d4c022013-07-18 22:58:1610372 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310373 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110374 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210375 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810376 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210377 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210378 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210379 http_server_properties->SetAlternativeService(
10380 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210381 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110382
[email protected]262eec82013-03-19 21:01:3610383 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010384 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110385 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110386
[email protected]49639fa2011-12-20 23:22:4110387 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:3610388 &restricted_port_request,
10389 callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110390 EXPECT_EQ(ERR_IO_PENDING, rv);
10391 // Valid change to restricted port should pass.
10392 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110393}
10394
bnc55ff9da2015-08-19 18:42:3510395// Ensure that we are not allowed to redirect traffic via an alternate protocol
10396// to an unrestricted (port >= 1024) when the original traffic was on a
10397// restricted port (port < 1024). Ensure that we can redirect in all other
10398// cases.
[email protected]23e482282013-06-14 16:08:0210399TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310400 AlternateProtocolPortUnrestrictedAllowed1) {
bnc55ff9da2015-08-19 18:42:3510401 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110402
10403 HttpRequestInfo unrestricted_port_request;
10404 unrestricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310405 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110406 unrestricted_port_request.load_flags = 0;
10407
[email protected]d973e99a2012-02-17 21:02:3610408 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110409 StaticSocketDataProvider first_data;
10410 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710411 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110412
10413 MockRead data_reads[] = {
10414 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10415 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610416 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110417 };
10418 StaticSocketDataProvider second_data(
10419 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710420 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110421
mmenkee65e7af2015-10-13 17:16:4210422 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110423
[email protected]30d4c022013-07-18 22:58:1610424 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310425 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110426 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210427 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810428 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210429 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210430 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210431 http_server_properties->SetAlternativeService(
10432 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210433 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110434
[email protected]262eec82013-03-19 21:01:3610435 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010436 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110437 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110438
[email protected]49639fa2011-12-20 23:22:4110439 int rv = trans->Start(
10440 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110441 EXPECT_EQ(ERR_IO_PENDING, rv);
10442 // Valid change to restricted port should pass.
10443 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110444}
10445
bnc55ff9da2015-08-19 18:42:3510446// Ensure that we are not allowed to redirect traffic via an alternate protocol
10447// to an unrestricted (port >= 1024) when the original traffic was on a
10448// restricted port (port < 1024). Ensure that we can redirect in all other
10449// cases.
[email protected]23e482282013-06-14 16:08:0210450TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310451 AlternateProtocolPortUnrestrictedAllowed2) {
bnc55ff9da2015-08-19 18:42:3510452 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110453
10454 HttpRequestInfo unrestricted_port_request;
10455 unrestricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310456 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110457 unrestricted_port_request.load_flags = 0;
10458
[email protected]d973e99a2012-02-17 21:02:3610459 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110460 StaticSocketDataProvider first_data;
10461 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710462 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110463
10464 MockRead data_reads[] = {
10465 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10466 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610467 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110468 };
10469 StaticSocketDataProvider second_data(
10470 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710471 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110472
mmenkee65e7af2015-10-13 17:16:4210473 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110474
[email protected]30d4c022013-07-18 22:58:1610475 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310476 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2210477 const int kUnrestrictedAlternatePort = 1025;
bnccacc0992015-03-20 20:22:2210478 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810479 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210480 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210481 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210482 http_server_properties->SetAlternativeService(
10483 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210484 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110485
[email protected]262eec82013-03-19 21:01:3610486 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010487 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110488 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110489
[email protected]49639fa2011-12-20 23:22:4110490 int rv = trans->Start(
10491 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110492 EXPECT_EQ(ERR_IO_PENDING, rv);
10493 // Valid change to an unrestricted port should pass.
10494 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110495}
10496
bnc55ff9da2015-08-19 18:42:3510497// Ensure that we are not allowed to redirect traffic via an alternate protocol
10498// to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
10499// once the alternate protocol request fails.
[email protected]d7599122014-05-24 03:37:2310500TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
bnc55ff9da2015-08-19 18:42:3510501 session_deps_.use_alternative_services = true;
[email protected]eb6234e2012-01-19 01:50:0210502
10503 HttpRequestInfo request;
10504 request.method = "GET";
bncce36dca22015-04-21 22:11:2310505 request.url = GURL("http://www.example.org/");
[email protected]eb6234e2012-01-19 01:50:0210506 request.load_flags = 0;
10507
10508 // The alternate protocol request will error out before we attempt to connect,
10509 // so only the standard HTTP request will try to connect.
10510 MockRead data_reads[] = {
10511 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10512 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610513 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0210514 };
10515 StaticSocketDataProvider data(
10516 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710517 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0210518
mmenkee65e7af2015-10-13 17:16:4210519 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0210520
[email protected]30d4c022013-07-18 22:58:1610521 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0210522 session->http_server_properties();
10523 const int kUnsafePort = 7;
bnccacc0992015-03-20 20:22:2210524 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810525 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210526 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1210527 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210528 http_server_properties->SetAlternativeService(
bnc7dc7e1b42015-07-28 14:43:1210529 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
[email protected]eb6234e2012-01-19 01:50:0210530
[email protected]262eec82013-03-19 21:01:3610531 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010532 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]eb6234e2012-01-19 01:50:0210533 TestCompletionCallback callback;
10534
10535 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10536 EXPECT_EQ(ERR_IO_PENDING, rv);
10537 // The HTTP request should succeed.
10538 EXPECT_EQ(OK, callback.WaitForResult());
10539
[email protected]eb6234e2012-01-19 01:50:0210540 const HttpResponseInfo* response = trans->GetResponseInfo();
10541 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010542 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]eb6234e2012-01-19 01:50:0210543 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10544
10545 std::string response_data;
10546 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10547 EXPECT_EQ("hello world", response_data);
10548}
10549
[email protected]23e482282013-06-14 16:08:0210550TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510551 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310552 session_deps_.next_protos = SpdyNextProtos();
[email protected]2ff8b312010-04-26 22:20:5410553
10554 HttpRequestInfo request;
10555 request.method = "GET";
bncce36dca22015-04-21 22:11:2310556 request.url = GURL("http://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5410557 request.load_flags = 0;
10558
[email protected]8a0fc822013-06-27 20:52:4310559 std::string alternate_protocol_http_header =
10560 GetAlternateProtocolHttpHeader();
10561
[email protected]2ff8b312010-04-26 22:20:5410562 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210563 MockRead("HTTP/1.1 200 OK\r\n"),
10564 MockRead(alternate_protocol_http_header.c_str()),
10565 MockRead("\r\n"),
10566 MockRead("hello world"),
10567 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10568 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5410569
10570 StaticSocketDataProvider first_transaction(
10571 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710572 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2ff8b312010-04-26 22:20:5410573
[email protected]8ddf8322012-02-23 18:08:0610574 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810575 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310576 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10577 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710578 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2ff8b312010-04-26 22:20:5410579
[email protected]cdf8f7e72013-05-23 10:56:4610580 scoped_ptr<SpdyFrame> req(
10581 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1310582 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]2ff8b312010-04-26 22:20:5410583
[email protected]23e482282013-06-14 16:08:0210584 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10585 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5410586 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310587 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5410588 };
10589
rch8e6c6c42015-05-01 14:05:1310590 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10591 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710592 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5410593
[email protected]d973e99a2012-02-17 21:02:3610594 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510595 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10596 NULL, 0, NULL, 0);
10597 hanging_non_alternate_protocol_socket.set_connect_data(
10598 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710599 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510600 &hanging_non_alternate_protocol_socket);
10601
[email protected]49639fa2011-12-20 23:22:4110602 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5410603
mmenkee65e7af2015-10-13 17:16:4210604 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610605 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010606 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410607
[email protected]49639fa2011-12-20 23:22:4110608 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410609 EXPECT_EQ(ERR_IO_PENDING, rv);
10610 EXPECT_EQ(OK, callback.WaitForResult());
10611
10612 const HttpResponseInfo* response = trans->GetResponseInfo();
10613 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010614 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5410615 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10616
10617 std::string response_data;
10618 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10619 EXPECT_EQ("hello world", response_data);
10620
[email protected]90499482013-06-01 00:39:5010621 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410622
[email protected]49639fa2011-12-20 23:22:4110623 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410624 EXPECT_EQ(ERR_IO_PENDING, rv);
10625 EXPECT_EQ(OK, callback.WaitForResult());
10626
10627 response = trans->GetResponseInfo();
10628 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010629 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210630 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310631 EXPECT_TRUE(response->was_fetched_via_spdy);
10632 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5410633
10634 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10635 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5410636}
10637
[email protected]23e482282013-06-14 16:08:0210638TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
bnc55ff9da2015-08-19 18:42:3510639 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310640 session_deps_.next_protos = SpdyNextProtos();
[email protected]2d6728692011-03-12 01:39:5510641
10642 HttpRequestInfo request;
10643 request.method = "GET";
bncce36dca22015-04-21 22:11:2310644 request.url = GURL("http://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510645 request.load_flags = 0;
10646
[email protected]8a0fc822013-06-27 20:52:4310647 std::string alternate_protocol_http_header =
10648 GetAlternateProtocolHttpHeader();
10649
[email protected]2d6728692011-03-12 01:39:5510650 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210651 MockRead("HTTP/1.1 200 OK\r\n"),
10652 MockRead(alternate_protocol_http_header.c_str()),
10653 MockRead("\r\n"),
10654 MockRead("hello world"),
10655 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10656 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510657 };
10658
10659 StaticSocketDataProvider first_transaction(
10660 data_reads, arraysize(data_reads), NULL, 0);
10661 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
[email protected]bb88e1d32013-05-03 23:11:0710662 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510663
[email protected]d973e99a2012-02-17 21:02:3610664 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
mmenkecc2298e2015-12-07 18:20:1810665 StaticSocketDataProvider hanging_socket1(NULL, 0, NULL, 0);
10666 hanging_socket1.set_connect_data(never_finishing_connect);
[email protected]2d6728692011-03-12 01:39:5510667 // Socket 2 and 3 are the hanging Alternate-Protocol and
10668 // non-Alternate-Protocol jobs from the 2nd transaction.
mmenkecc2298e2015-12-07 18:20:1810669 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
10670
10671 StaticSocketDataProvider hanging_socket2(NULL, 0, NULL, 0);
10672 hanging_socket2.set_connect_data(never_finishing_connect);
10673 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5510674
[email protected]8ddf8322012-02-23 18:08:0610675 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810676 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310677 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10678 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710679 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510680
[email protected]cdf8f7e72013-05-23 10:56:4610681 scoped_ptr<SpdyFrame> req1(
10682 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10683 scoped_ptr<SpdyFrame> req2(
10684 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]2d6728692011-03-12 01:39:5510685 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1310686 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
[email protected]2d6728692011-03-12 01:39:5510687 };
[email protected]23e482282013-06-14 16:08:0210688 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10689 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
10690 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10691 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5510692 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310693 CreateMockRead(*resp1, 2),
10694 CreateMockRead(*data1, 3),
10695 CreateMockRead(*resp2, 4),
10696 CreateMockRead(*data2, 5),
10697 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5510698 };
10699
rch8e6c6c42015-05-01 14:05:1310700 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10701 arraysize(spdy_writes));
[email protected]2d6728692011-03-12 01:39:5510702 // Socket 4 is the successful Alternate-Protocol for transaction 3.
[email protected]bb88e1d32013-05-03 23:11:0710703 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5510704
10705 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
mmenkecc2298e2015-12-07 18:20:1810706 StaticSocketDataProvider hanging_socket3(NULL, 0, NULL, 0);
10707 hanging_socket3.set_connect_data(never_finishing_connect);
10708 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5510709
mmenkee65e7af2015-10-13 17:16:4210710 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4110711 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5010712 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5510713
[email protected]49639fa2011-12-20 23:22:4110714 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510715 EXPECT_EQ(ERR_IO_PENDING, rv);
10716 EXPECT_EQ(OK, callback1.WaitForResult());
10717
10718 const HttpResponseInfo* response = trans1.GetResponseInfo();
10719 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010720 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510721 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10722
10723 std::string response_data;
10724 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10725 EXPECT_EQ("hello world", response_data);
10726
[email protected]49639fa2011-12-20 23:22:4110727 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5010728 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110729 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510730 EXPECT_EQ(ERR_IO_PENDING, rv);
10731
[email protected]49639fa2011-12-20 23:22:4110732 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5010733 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110734 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510735 EXPECT_EQ(ERR_IO_PENDING, rv);
10736
10737 EXPECT_EQ(OK, callback2.WaitForResult());
10738 EXPECT_EQ(OK, callback3.WaitForResult());
10739
10740 response = trans2.GetResponseInfo();
10741 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010742 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210743 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5510744 EXPECT_TRUE(response->was_fetched_via_spdy);
10745 EXPECT_TRUE(response->was_npn_negotiated);
10746 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10747 EXPECT_EQ("hello!", response_data);
10748
10749 response = trans3.GetResponseInfo();
10750 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010751 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210752 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5510753 EXPECT_TRUE(response->was_fetched_via_spdy);
10754 EXPECT_TRUE(response->was_npn_negotiated);
10755 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
10756 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5510757}
10758
[email protected]23e482282013-06-14 16:08:0210759TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510760 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310761 session_deps_.next_protos = SpdyNextProtos();
[email protected]2d6728692011-03-12 01:39:5510762
10763 HttpRequestInfo request;
10764 request.method = "GET";
bncce36dca22015-04-21 22:11:2310765 request.url = GURL("http://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510766 request.load_flags = 0;
10767
[email protected]8a0fc822013-06-27 20:52:4310768 std::string alternate_protocol_http_header =
10769 GetAlternateProtocolHttpHeader();
10770
[email protected]2d6728692011-03-12 01:39:5510771 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210772 MockRead("HTTP/1.1 200 OK\r\n"),
10773 MockRead(alternate_protocol_http_header.c_str()),
10774 MockRead("\r\n"),
10775 MockRead("hello world"),
10776 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10777 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510778 };
10779
10780 StaticSocketDataProvider first_transaction(
10781 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710782 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510783
[email protected]8ddf8322012-02-23 18:08:0610784 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810785 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0710786 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510787
[email protected]d973e99a2012-02-17 21:02:3610788 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510789 StaticSocketDataProvider hanging_alternate_protocol_socket(
10790 NULL, 0, NULL, 0);
10791 hanging_alternate_protocol_socket.set_connect_data(
10792 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710793 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510794 &hanging_alternate_protocol_socket);
10795
10796 // 2nd request is just a copy of the first one, over HTTP again.
mmenkecc2298e2015-12-07 18:20:1810797 StaticSocketDataProvider second_transaction(data_reads, arraysize(data_reads),
10798 NULL, 0);
10799 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
[email protected]2d6728692011-03-12 01:39:5510800
[email protected]49639fa2011-12-20 23:22:4110801 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5510802
mmenkee65e7af2015-10-13 17:16:4210803 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610804 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010805 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510806
[email protected]49639fa2011-12-20 23:22:4110807 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510808 EXPECT_EQ(ERR_IO_PENDING, rv);
10809 EXPECT_EQ(OK, callback.WaitForResult());
10810
10811 const HttpResponseInfo* response = trans->GetResponseInfo();
10812 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010813 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510814 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10815
10816 std::string response_data;
10817 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10818 EXPECT_EQ("hello world", response_data);
10819
[email protected]90499482013-06-01 00:39:5010820 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510821
[email protected]49639fa2011-12-20 23:22:4110822 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510823 EXPECT_EQ(ERR_IO_PENDING, rv);
10824 EXPECT_EQ(OK, callback.WaitForResult());
10825
10826 response = trans->GetResponseInfo();
10827 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010828 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510829 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10830 EXPECT_FALSE(response->was_fetched_via_spdy);
10831 EXPECT_FALSE(response->was_npn_negotiated);
10832
10833 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10834 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5510835}
10836
[email protected]631f1322010-04-30 17:59:1110837class CapturingProxyResolver : public ProxyResolver {
10838 public:
sammce90c9212015-05-27 23:43:3510839 CapturingProxyResolver() {}
dchengb03027d2014-10-21 12:00:2010840 ~CapturingProxyResolver() override {}
[email protected]631f1322010-04-30 17:59:1110841
dchengb03027d2014-10-21 12:00:2010842 int GetProxyForURL(const GURL& url,
10843 ProxyInfo* results,
10844 const CompletionCallback& callback,
10845 RequestHandle* request,
10846 const BoundNetLog& net_log) override {
[email protected]fae7669f2010-08-02 21:49:4010847 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
10848 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:4210849 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:1110850 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:4210851 return OK;
[email protected]631f1322010-04-30 17:59:1110852 }
10853
dchengb03027d2014-10-21 12:00:2010854 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
[email protected]631f1322010-04-30 17:59:1110855
dchengb03027d2014-10-21 12:00:2010856 LoadState GetLoadState(RequestHandle request) const override {
[email protected]f2c971f2011-11-08 00:33:1710857 NOTREACHED();
10858 return LOAD_STATE_IDLE;
10859 }
10860
[email protected]24476402010-07-20 20:55:1710861 const std::vector<GURL>& resolved() const { return resolved_; }
10862
10863 private:
[email protected]631f1322010-04-30 17:59:1110864 std::vector<GURL> resolved_;
10865
10866 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
10867};
10868
sammce64b2362015-04-29 03:50:2310869class CapturingProxyResolverFactory : public ProxyResolverFactory {
10870 public:
10871 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
10872 : ProxyResolverFactory(false), resolver_(resolver) {}
10873
10874 int CreateProxyResolver(
10875 const scoped_refptr<ProxyResolverScriptData>& pac_script,
10876 scoped_ptr<ProxyResolver>* resolver,
10877 const net::CompletionCallback& callback,
10878 scoped_ptr<Request>* request) override {
10879 resolver->reset(new ForwardingProxyResolver(resolver_));
10880 return OK;
10881 }
10882
10883 private:
10884 ProxyResolver* resolver_;
10885};
10886
[email protected]23e482282013-06-14 16:08:0210887TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310888 UseAlternateProtocolForTunneledNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510889 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310890 session_deps_.next_protos = SpdyNextProtos();
[email protected]631f1322010-04-30 17:59:1110891
10892 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4210893 proxy_config.set_auto_detect(true);
10894 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1110895
sammc5dd160c2015-04-02 02:43:1310896 CapturingProxyResolver capturing_proxy_resolver;
[email protected]bb88e1d32013-05-03 23:11:0710897 session_deps_.proxy_service.reset(new ProxyService(
csharrisonb7e3a082015-09-22 19:13:0410898 make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)),
sammc5dd160c2015-04-02 02:43:1310899 make_scoped_ptr(
sammce64b2362015-04-29 03:50:2310900 new CapturingProxyResolverFactory(&capturing_proxy_resolver)),
[email protected]66761b952010-06-25 21:30:3810901 NULL));
vishal.b62985ca92015-04-17 08:45:5110902 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710903 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1110904
10905 HttpRequestInfo request;
10906 request.method = "GET";
bncce36dca22015-04-21 22:11:2310907 request.url = GURL("http://www.example.org/");
[email protected]631f1322010-04-30 17:59:1110908 request.load_flags = 0;
10909
[email protected]8a0fc822013-06-27 20:52:4310910 std::string alternate_protocol_http_header =
10911 GetAlternateProtocolHttpHeader();
10912
[email protected]631f1322010-04-30 17:59:1110913 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210914 MockRead("HTTP/1.1 200 OK\r\n"),
10915 MockRead(alternate_protocol_http_header.c_str()),
10916 MockRead("\r\n"),
10917 MockRead("hello world"),
10918 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10919 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1110920 };
10921
10922 StaticSocketDataProvider first_transaction(
10923 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710924 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]631f1322010-04-30 17:59:1110925
[email protected]8ddf8322012-02-23 18:08:0610926 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810927 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310928 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10929 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710930 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]631f1322010-04-30 17:59:1110931
[email protected]cdf8f7e72013-05-23 10:56:4610932 scoped_ptr<SpdyFrame> req(
10933 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]631f1322010-04-30 17:59:1110934 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1310935 MockWrite(ASYNC, 0,
10936 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1710937 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1310938 "Proxy-Connection: keep-alive\r\n\r\n"),
10939 CreateMockWrite(*req, 2),
[email protected]631f1322010-04-30 17:59:1110940 };
10941
[email protected]d911f1b2010-05-05 22:39:4210942 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10943
[email protected]23e482282013-06-14 16:08:0210944 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10945 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:1110946 MockRead spdy_reads[] = {
mmenkee24011922015-12-17 22:12:5910947 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(*resp.get(), 3),
10948 CreateMockRead(*data.get(), 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1110949 };
10950
rch8e6c6c42015-05-01 14:05:1310951 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10952 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710953 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1110954
[email protected]d973e99a2012-02-17 21:02:3610955 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510956 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10957 NULL, 0, NULL, 0);
10958 hanging_non_alternate_protocol_socket.set_connect_data(
10959 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710960 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510961 &hanging_non_alternate_protocol_socket);
10962
[email protected]49639fa2011-12-20 23:22:4110963 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1110964
mmenkee65e7af2015-10-13 17:16:4210965 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610966 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010967 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1110968
[email protected]49639fa2011-12-20 23:22:4110969 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:1110970 EXPECT_EQ(ERR_IO_PENDING, rv);
10971 EXPECT_EQ(OK, callback.WaitForResult());
10972
10973 const HttpResponseInfo* response = trans->GetResponseInfo();
10974 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010975 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]631f1322010-04-30 17:59:1110976 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310977 EXPECT_FALSE(response->was_fetched_via_spdy);
10978 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:1110979
10980 std::string response_data;
10981 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10982 EXPECT_EQ("hello world", response_data);
10983
[email protected]90499482013-06-01 00:39:5010984 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1110985
[email protected]49639fa2011-12-20 23:22:4110986 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:1110987 EXPECT_EQ(ERR_IO_PENDING, rv);
10988 EXPECT_EQ(OK, callback.WaitForResult());
10989
10990 response = trans->GetResponseInfo();
10991 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010992 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210993 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310994 EXPECT_TRUE(response->was_fetched_via_spdy);
10995 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:1110996
10997 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10998 EXPECT_EQ("hello!", response_data);
sammc5dd160c2015-04-02 02:43:1310999 ASSERT_EQ(3u, capturing_proxy_resolver.resolved().size());
bncce36dca22015-04-21 22:11:2311000 EXPECT_EQ("http://www.example.org/",
sammc5dd160c2015-04-02 02:43:1311001 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2311002 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1311003 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1111004
[email protected]029c83b62013-01-24 05:28:2011005 LoadTimingInfo load_timing_info;
11006 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11007 TestLoadTimingNotReusedWithPac(load_timing_info,
11008 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1111009}
[email protected]631f1322010-04-30 17:59:1111010
[email protected]23e482282013-06-14 16:08:0211011TEST_P(HttpNetworkTransactionTest,
[email protected]2ff8b312010-04-26 22:20:5411012 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
bnc55ff9da2015-08-19 18:42:3511013 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311014 session_deps_.next_protos = SpdyNextProtos();
[email protected]2ff8b312010-04-26 22:20:5411015
11016 HttpRequestInfo request;
11017 request.method = "GET";
bncce36dca22015-04-21 22:11:2311018 request.url = GURL("http://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5411019 request.load_flags = 0;
11020
[email protected]8a0fc822013-06-27 20:52:4311021 std::string alternate_protocol_http_header =
11022 GetAlternateProtocolHttpHeader();
11023
[email protected]2ff8b312010-04-26 22:20:5411024 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211025 MockRead("HTTP/1.1 200 OK\r\n"),
11026 MockRead(alternate_protocol_http_header.c_str()),
11027 MockRead("\r\n"),
11028 MockRead("hello world"),
11029 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5411030 };
11031
11032 StaticSocketDataProvider first_transaction(
11033 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0711034 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2ff8b312010-04-26 22:20:5411035
[email protected]8ddf8322012-02-23 18:08:0611036 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811037 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2311038 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11039 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0711040 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2ff8b312010-04-26 22:20:5411041
[email protected]cdf8f7e72013-05-23 10:56:4611042 scoped_ptr<SpdyFrame> req(
11043 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1311044 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]2ff8b312010-04-26 22:20:5411045
[email protected]23e482282013-06-14 16:08:0211046 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11047 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5411048 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1311049 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5411050 };
11051
rch8e6c6c42015-05-01 14:05:1311052 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11053 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711054 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5411055
[email protected]83039bb2011-12-09 18:43:5511056 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5411057
mmenkee65e7af2015-10-13 17:16:4211058 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5411059
[email protected]262eec82013-03-19 21:01:3611060 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011061 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5411062
[email protected]49639fa2011-12-20 23:22:4111063 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5411064 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4111065 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:5411066
11067 const HttpResponseInfo* response = trans->GetResponseInfo();
11068 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011069 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5411070 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11071
11072 std::string response_data;
11073 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11074 EXPECT_EQ("hello world", response_data);
11075
11076 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2311077 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4011078 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5311079 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2711080 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:4211081 CreateSecureSpdySession(session.get(), key, BoundNetLog());
[email protected]02b0c342010-09-25 21:09:3811082
[email protected]90499482013-06-01 00:39:5011083 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5411084
[email protected]49639fa2011-12-20 23:22:4111085 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5411086 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4111087 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:5411088
11089 response = trans->GetResponseInfo();
11090 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011091 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0211092 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5311093 EXPECT_TRUE(response->was_fetched_via_spdy);
11094 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5411095
11096 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11097 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4211098}
11099
[email protected]044de0642010-06-17 10:42:1511100// GenerateAuthToken is a mighty big test.
11101// It tests all permutation of GenerateAuthToken behavior:
11102// - Synchronous and Asynchronous completion.
11103// - OK or error on completion.
11104// - Direct connection, non-authenticating proxy, and authenticating proxy.
11105// - HTTP or HTTPS backend (to include proxy tunneling).
11106// - Non-authenticating and authenticating backend.
11107//
[email protected]fe3b7dc2012-02-03 19:52:0911108// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1511109// problems generating an auth token for an authenticating proxy, we don't
11110// need to test all permutations of the backend server).
11111//
11112// The test proceeds by going over each of the configuration cases, and
11113// potentially running up to three rounds in each of the tests. The TestConfig
11114// specifies both the configuration for the test as well as the expectations
11115// for the results.
[email protected]23e482282013-06-14 16:08:0211116TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5011117 static const char kServer[] = "http://www.example.com";
11118 static const char kSecureServer[] = "https://www.example.com";
11119 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1511120 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
11121
11122 enum AuthTiming {
11123 AUTH_NONE,
11124 AUTH_SYNC,
11125 AUTH_ASYNC,
11126 };
11127
11128 const MockWrite kGet(
11129 "GET / HTTP/1.1\r\n"
11130 "Host: www.example.com\r\n"
11131 "Connection: keep-alive\r\n\r\n");
11132 const MockWrite kGetProxy(
11133 "GET http://www.example.com/ HTTP/1.1\r\n"
11134 "Host: www.example.com\r\n"
11135 "Proxy-Connection: keep-alive\r\n\r\n");
11136 const MockWrite kGetAuth(
11137 "GET / HTTP/1.1\r\n"
11138 "Host: www.example.com\r\n"
11139 "Connection: keep-alive\r\n"
11140 "Authorization: auth_token\r\n\r\n");
11141 const MockWrite kGetProxyAuth(
11142 "GET http://www.example.com/ HTTP/1.1\r\n"
11143 "Host: www.example.com\r\n"
11144 "Proxy-Connection: keep-alive\r\n"
11145 "Proxy-Authorization: auth_token\r\n\r\n");
11146 const MockWrite kGetAuthThroughProxy(
11147 "GET http://www.example.com/ HTTP/1.1\r\n"
11148 "Host: www.example.com\r\n"
11149 "Proxy-Connection: keep-alive\r\n"
11150 "Authorization: auth_token\r\n\r\n");
11151 const MockWrite kGetAuthWithProxyAuth(
11152 "GET http://www.example.com/ HTTP/1.1\r\n"
11153 "Host: www.example.com\r\n"
11154 "Proxy-Connection: keep-alive\r\n"
11155 "Proxy-Authorization: auth_token\r\n"
11156 "Authorization: auth_token\r\n\r\n");
11157 const MockWrite kConnect(
11158 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711159 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1511160 "Proxy-Connection: keep-alive\r\n\r\n");
11161 const MockWrite kConnectProxyAuth(
11162 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711163 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1511164 "Proxy-Connection: keep-alive\r\n"
11165 "Proxy-Authorization: auth_token\r\n\r\n");
11166
11167 const MockRead kSuccess(
11168 "HTTP/1.1 200 OK\r\n"
11169 "Content-Type: text/html; charset=iso-8859-1\r\n"
11170 "Content-Length: 3\r\n\r\n"
11171 "Yes");
11172 const MockRead kFailure(
11173 "Should not be called.");
11174 const MockRead kServerChallenge(
11175 "HTTP/1.1 401 Unauthorized\r\n"
11176 "WWW-Authenticate: Mock realm=server\r\n"
11177 "Content-Type: text/html; charset=iso-8859-1\r\n"
11178 "Content-Length: 14\r\n\r\n"
11179 "Unauthorized\r\n");
11180 const MockRead kProxyChallenge(
11181 "HTTP/1.1 407 Unauthorized\r\n"
11182 "Proxy-Authenticate: Mock realm=proxy\r\n"
11183 "Proxy-Connection: close\r\n"
11184 "Content-Type: text/html; charset=iso-8859-1\r\n"
11185 "Content-Length: 14\r\n\r\n"
11186 "Unauthorized\r\n");
11187 const MockRead kProxyConnected(
11188 "HTTP/1.1 200 Connection Established\r\n\r\n");
11189
11190 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
11191 // no constructors, but the C++ compiler on Windows warns about
11192 // unspecified data in compound literals. So, moved to using constructors,
11193 // and TestRound's created with the default constructor should not be used.
11194 struct TestRound {
11195 TestRound()
11196 : expected_rv(ERR_UNEXPECTED),
11197 extra_write(NULL),
11198 extra_read(NULL) {
11199 }
11200 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
11201 int expected_rv_arg)
11202 : write(write_arg),
11203 read(read_arg),
11204 expected_rv(expected_rv_arg),
11205 extra_write(NULL),
11206 extra_read(NULL) {
11207 }
11208 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
11209 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0111210 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1511211 : write(write_arg),
11212 read(read_arg),
11213 expected_rv(expected_rv_arg),
11214 extra_write(extra_write_arg),
11215 extra_read(extra_read_arg) {
11216 }
11217 MockWrite write;
11218 MockRead read;
11219 int expected_rv;
11220 const MockWrite* extra_write;
11221 const MockRead* extra_read;
11222 };
11223
11224 static const int kNoSSL = 500;
11225
11226 struct TestConfig {
thestig9d3bb0c2015-01-24 00:49:5111227 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1511228 AuthTiming proxy_auth_timing;
11229 int proxy_auth_rv;
thestig9d3bb0c2015-01-24 00:49:5111230 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1511231 AuthTiming server_auth_timing;
11232 int server_auth_rv;
11233 int num_auth_rounds;
11234 int first_ssl_round;
11235 TestRound rounds[3];
11236 } test_configs[] = {
11237 // Non-authenticating HTTP server with a direct connection.
11238 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
11239 { TestRound(kGet, kSuccess, OK)}},
11240 // Authenticating HTTP server with a direct connection.
11241 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
11242 { TestRound(kGet, kServerChallenge, OK),
11243 TestRound(kGetAuth, kSuccess, OK)}},
11244 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
11245 { TestRound(kGet, kServerChallenge, OK),
11246 TestRound(kGetAuth, kFailure, kAuthErr)}},
11247 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
11248 { TestRound(kGet, kServerChallenge, OK),
11249 TestRound(kGetAuth, kSuccess, OK)}},
11250 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
11251 { TestRound(kGet, kServerChallenge, OK),
11252 TestRound(kGetAuth, kFailure, kAuthErr)}},
11253 // Non-authenticating HTTP server through a non-authenticating proxy.
11254 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
11255 { TestRound(kGetProxy, kSuccess, OK)}},
11256 // Authenticating HTTP server through a non-authenticating proxy.
11257 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
11258 { TestRound(kGetProxy, kServerChallenge, OK),
11259 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
11260 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
11261 { TestRound(kGetProxy, kServerChallenge, OK),
11262 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
11263 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
11264 { TestRound(kGetProxy, kServerChallenge, OK),
11265 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
11266 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
11267 { TestRound(kGetProxy, kServerChallenge, OK),
11268 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
11269 // Non-authenticating HTTP server through an authenticating proxy.
11270 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
11271 { TestRound(kGetProxy, kProxyChallenge, OK),
11272 TestRound(kGetProxyAuth, kSuccess, OK)}},
11273 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
11274 { TestRound(kGetProxy, kProxyChallenge, OK),
11275 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
11276 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
11277 { TestRound(kGetProxy, kProxyChallenge, OK),
11278 TestRound(kGetProxyAuth, kSuccess, OK)}},
11279 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
11280 { TestRound(kGetProxy, kProxyChallenge, OK),
11281 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
11282 // Authenticating HTTP server through an authenticating proxy.
11283 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
11284 { TestRound(kGetProxy, kProxyChallenge, OK),
11285 TestRound(kGetProxyAuth, kServerChallenge, OK),
11286 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11287 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
11288 { TestRound(kGetProxy, kProxyChallenge, OK),
11289 TestRound(kGetProxyAuth, kServerChallenge, OK),
11290 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11291 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
11292 { TestRound(kGetProxy, kProxyChallenge, OK),
11293 TestRound(kGetProxyAuth, kServerChallenge, OK),
11294 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11295 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
11296 { TestRound(kGetProxy, kProxyChallenge, OK),
11297 TestRound(kGetProxyAuth, kServerChallenge, OK),
11298 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11299 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
11300 { TestRound(kGetProxy, kProxyChallenge, OK),
11301 TestRound(kGetProxyAuth, kServerChallenge, OK),
11302 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11303 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
11304 { TestRound(kGetProxy, kProxyChallenge, OK),
11305 TestRound(kGetProxyAuth, kServerChallenge, OK),
11306 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11307 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
11308 { TestRound(kGetProxy, kProxyChallenge, OK),
11309 TestRound(kGetProxyAuth, kServerChallenge, OK),
11310 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11311 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
11312 { TestRound(kGetProxy, kProxyChallenge, OK),
11313 TestRound(kGetProxyAuth, kServerChallenge, OK),
11314 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11315 // Non-authenticating HTTPS server with a direct connection.
11316 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
11317 { TestRound(kGet, kSuccess, OK)}},
11318 // Authenticating HTTPS server with a direct connection.
11319 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
11320 { TestRound(kGet, kServerChallenge, OK),
11321 TestRound(kGetAuth, kSuccess, OK)}},
11322 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
11323 { TestRound(kGet, kServerChallenge, OK),
11324 TestRound(kGetAuth, kFailure, kAuthErr)}},
11325 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
11326 { TestRound(kGet, kServerChallenge, OK),
11327 TestRound(kGetAuth, kSuccess, OK)}},
11328 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
11329 { TestRound(kGet, kServerChallenge, OK),
11330 TestRound(kGetAuth, kFailure, kAuthErr)}},
11331 // Non-authenticating HTTPS server with a non-authenticating proxy.
11332 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
11333 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
11334 // Authenticating HTTPS server through a non-authenticating proxy.
11335 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
11336 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11337 TestRound(kGetAuth, kSuccess, OK)}},
11338 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
11339 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11340 TestRound(kGetAuth, kFailure, kAuthErr)}},
11341 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
11342 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11343 TestRound(kGetAuth, kSuccess, OK)}},
11344 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
11345 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11346 TestRound(kGetAuth, kFailure, kAuthErr)}},
11347 // Non-Authenticating HTTPS server through an authenticating proxy.
11348 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
11349 { TestRound(kConnect, kProxyChallenge, OK),
11350 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
11351 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
11352 { TestRound(kConnect, kProxyChallenge, OK),
11353 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
11354 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
11355 { TestRound(kConnect, kProxyChallenge, OK),
11356 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
11357 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
11358 { TestRound(kConnect, kProxyChallenge, OK),
11359 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
11360 // Authenticating HTTPS server through an authenticating proxy.
11361 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11362 { TestRound(kConnect, kProxyChallenge, OK),
11363 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11364 &kGet, &kServerChallenge),
11365 TestRound(kGetAuth, kSuccess, OK)}},
11366 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11367 { TestRound(kConnect, kProxyChallenge, OK),
11368 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11369 &kGet, &kServerChallenge),
11370 TestRound(kGetAuth, kFailure, kAuthErr)}},
11371 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11372 { TestRound(kConnect, kProxyChallenge, OK),
11373 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11374 &kGet, &kServerChallenge),
11375 TestRound(kGetAuth, kSuccess, OK)}},
11376 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11377 { TestRound(kConnect, kProxyChallenge, OK),
11378 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11379 &kGet, &kServerChallenge),
11380 TestRound(kGetAuth, kFailure, kAuthErr)}},
11381 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11382 { TestRound(kConnect, kProxyChallenge, OK),
11383 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11384 &kGet, &kServerChallenge),
11385 TestRound(kGetAuth, kSuccess, OK)}},
11386 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11387 { TestRound(kConnect, kProxyChallenge, OK),
11388 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11389 &kGet, &kServerChallenge),
11390 TestRound(kGetAuth, kFailure, kAuthErr)}},
11391 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11392 { TestRound(kConnect, kProxyChallenge, OK),
11393 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11394 &kGet, &kServerChallenge),
11395 TestRound(kGetAuth, kSuccess, OK)}},
11396 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11397 { TestRound(kConnect, kProxyChallenge, OK),
11398 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11399 &kGet, &kServerChallenge),
11400 TestRound(kGetAuth, kFailure, kAuthErr)}},
11401 };
11402
viettrungluue4a8b882014-10-16 06:17:3811403 for (size_t i = 0; i < arraysize(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:0811404 HttpAuthHandlerMock::Factory* auth_factory(
11405 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711406 session_deps_.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:1511407 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:2611408
11409 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1511410 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:0811411 for (int n = 0; n < 2; n++) {
11412 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11413 std::string auth_challenge = "Mock realm=proxy";
11414 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2411415 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11416 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0811417 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
11418 origin, BoundNetLog());
11419 auth_handler->SetGenerateExpectation(
11420 test_config.proxy_auth_timing == AUTH_ASYNC,
11421 test_config.proxy_auth_rv);
11422 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
11423 }
[email protected]044de0642010-06-17 10:42:1511424 }
11425 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0011426 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1511427 std::string auth_challenge = "Mock realm=server";
11428 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2411429 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11430 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1511431 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
11432 origin, BoundNetLog());
11433 auth_handler->SetGenerateExpectation(
11434 test_config.server_auth_timing == AUTH_ASYNC,
11435 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:0811436 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1511437 }
11438 if (test_config.proxy_url) {
rdsmith82957ad2015-09-16 19:42:0311439 session_deps_.proxy_service =
11440 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:1511441 } else {
rdsmith82957ad2015-09-16 19:42:0311442 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1511443 }
11444
11445 HttpRequestInfo request;
11446 request.method = "GET";
11447 request.url = GURL(test_config.server_url);
11448 request.load_flags = 0;
11449
mmenkee65e7af2015-10-13 17:16:4211450 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1511451
rchcb68dc62015-05-21 04:45:3611452 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
11453
11454 std::vector<std::vector<MockRead>> mock_reads(1);
11455 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1511456 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11457 const TestRound& read_write_round = test_config.rounds[round];
11458
11459 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3611460 mock_reads.back().push_back(read_write_round.read);
11461 mock_writes.back().push_back(read_write_round.write);
11462
11463 // kProxyChallenge uses Proxy-Connection: close which means that the
11464 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5411465 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3611466 mock_reads.push_back(std::vector<MockRead>());
11467 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1511468 }
11469
rchcb68dc62015-05-21 04:45:3611470 if (read_write_round.extra_read) {
11471 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1511472 }
rchcb68dc62015-05-21 04:45:3611473 if (read_write_round.extra_write) {
11474 mock_writes.back().push_back(*read_write_round.extra_write);
11475 }
[email protected]044de0642010-06-17 10:42:1511476
11477 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1511478 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0711479 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1511480 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3611481 }
[email protected]044de0642010-06-17 10:42:1511482
olli.raula525048c2015-12-10 07:38:3211483 std::vector<scoped_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3611484 for (size_t i = 0; i < mock_reads.size(); ++i) {
olli.raula525048c2015-12-10 07:38:3211485 data_providers.push_back(make_scoped_ptr(new StaticSocketDataProvider(
davidben5f8b6bc2015-11-25 03:19:5411486 mock_reads[i].data(), mock_reads[i].size(), mock_writes[i].data(),
olli.raula525048c2015-12-10 07:38:3211487 mock_writes[i].size())));
rchcb68dc62015-05-21 04:45:3611488 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3211489 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3611490 }
11491
mmenkecc2298e2015-12-07 18:20:1811492 // Transaction must be created after DataProviders, so it's destroyed before
11493 // they are as well.
11494 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11495
rchcb68dc62015-05-21 04:45:3611496 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11497 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1511498 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4111499 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1511500 int rv;
11501 if (round == 0) {
[email protected]49639fa2011-12-20 23:22:4111502 rv = trans.Start(&request, callback.callback(), BoundNetLog());
[email protected]044de0642010-06-17 10:42:1511503 } else {
[email protected]49639fa2011-12-20 23:22:4111504 rv = trans.RestartWithAuth(
11505 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1511506 }
11507 if (rv == ERR_IO_PENDING)
11508 rv = callback.WaitForResult();
11509
11510 // Compare results with expected data.
11511 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:5011512 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5511513 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1511514 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
11515 continue;
11516 }
11517 if (round + 1 < test_config.num_auth_rounds) {
11518 EXPECT_FALSE(response->auth_challenge.get() == NULL);
11519 } else {
11520 EXPECT_TRUE(response->auth_challenge.get() == NULL);
11521 }
11522 }
[email protected]e5ae96a2010-04-14 20:12:4511523 }
11524}
11525
[email protected]23e482282013-06-14 16:08:0211526TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1411527 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1411528 HttpAuthHandlerMock::Factory* auth_factory(
11529 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711530 session_deps_.http_auth_handler_factory.reset(auth_factory);
rdsmith82957ad2015-09-16 19:42:0311531 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0711532 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
11533 session_deps_.host_resolver->set_synchronous_mode(true);
[email protected]c871bce92010-07-15 21:51:1411534
11535 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11536 auth_handler->set_connection_based(true);
11537 std::string auth_challenge = "Mock realm=server";
11538 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2411539 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11540 auth_challenge.end());
[email protected]c871bce92010-07-15 21:51:1411541 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
11542 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:0811543 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1411544
[email protected]c871bce92010-07-15 21:51:1411545 int rv = OK;
11546 const HttpResponseInfo* response = NULL;
11547 HttpRequestInfo request;
11548 request.method = "GET";
11549 request.url = origin;
11550 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:2711551
mmenkee65e7af2015-10-13 17:16:4211552 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1011553
11554 // Use a TCP Socket Pool with only one connection per group. This is used
11555 // to validate that the TCP socket is not released to the pool between
11556 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4211557 HttpNetworkSessionPeer session_peer(session.get());
[email protected]ab739042011-04-07 15:22:2811558 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:1011559 50, // Max sockets for pool
11560 1, // Max sockets per group
[email protected]bb88e1d32013-05-03 23:11:0711561 session_deps_.host_resolver.get(),
11562 session_deps_.socket_factory.get(),
11563 session_deps_.net_log);
[email protected]831e4a32013-11-14 02:14:4411564 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
11565 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:0211566 mock_pool_manager->SetTransportSocketPool(transport_pool);
dchengc7eeda422015-12-26 03:56:4811567 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1011568
[email protected]262eec82013-03-19 21:01:3611569 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011570 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111571 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1411572
11573 const MockWrite kGet(
11574 "GET / HTTP/1.1\r\n"
11575 "Host: www.example.com\r\n"
11576 "Connection: keep-alive\r\n\r\n");
11577 const MockWrite kGetAuth(
11578 "GET / HTTP/1.1\r\n"
11579 "Host: www.example.com\r\n"
11580 "Connection: keep-alive\r\n"
11581 "Authorization: auth_token\r\n\r\n");
11582
11583 const MockRead kServerChallenge(
11584 "HTTP/1.1 401 Unauthorized\r\n"
11585 "WWW-Authenticate: Mock realm=server\r\n"
11586 "Content-Type: text/html; charset=iso-8859-1\r\n"
11587 "Content-Length: 14\r\n\r\n"
11588 "Unauthorized\r\n");
11589 const MockRead kSuccess(
11590 "HTTP/1.1 200 OK\r\n"
11591 "Content-Type: text/html; charset=iso-8859-1\r\n"
11592 "Content-Length: 3\r\n\r\n"
11593 "Yes");
11594
11595 MockWrite writes[] = {
11596 // First round
11597 kGet,
11598 // Second round
11599 kGetAuth,
11600 // Third round
11601 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3011602 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1011603 kGetAuth,
11604 // Competing request
11605 kGet,
[email protected]c871bce92010-07-15 21:51:1411606 };
11607 MockRead reads[] = {
11608 // First round
11609 kServerChallenge,
11610 // Second round
11611 kServerChallenge,
11612 // Third round
[email protected]eca50e122010-09-11 14:03:3011613 kServerChallenge,
11614 // Fourth round
[email protected]c871bce92010-07-15 21:51:1411615 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1011616 // Competing response
11617 kSuccess,
[email protected]c871bce92010-07-15 21:51:1411618 };
11619 StaticSocketDataProvider data_provider(reads, arraysize(reads),
11620 writes, arraysize(writes));
[email protected]bb88e1d32013-05-03 23:11:0711621 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1411622
thestig9d3bb0c2015-01-24 00:49:5111623 const char kSocketGroup[] = "www.example.com:80";
[email protected]7ef4cbbb2011-02-06 11:19:1011624
11625 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1411626 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111627 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]c871bce92010-07-15 21:51:1411628 if (rv == ERR_IO_PENDING)
11629 rv = callback.WaitForResult();
11630 EXPECT_EQ(OK, rv);
11631 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011632 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411633 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811634 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411635
[email protected]7ef4cbbb2011-02-06 11:19:1011636 // In between rounds, another request comes in for the same domain.
11637 // It should not be able to grab the TCP socket that trans has already
11638 // claimed.
11639 scoped_ptr<HttpTransaction> trans_compete(
[email protected]90499482013-06-01 00:39:5011640 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111641 TestCompletionCallback callback_compete;
11642 rv = trans_compete->Start(
11643 &request, callback_compete.callback(), BoundNetLog());
[email protected]7ef4cbbb2011-02-06 11:19:1011644 EXPECT_EQ(ERR_IO_PENDING, rv);
11645 // callback_compete.WaitForResult at this point would stall forever,
11646 // since the HttpNetworkTransaction does not release the request back to
11647 // the pool until after authentication completes.
11648
11649 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1411650 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111651 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411652 if (rv == ERR_IO_PENDING)
11653 rv = callback.WaitForResult();
11654 EXPECT_EQ(OK, rv);
11655 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011656 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411657 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811658 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411659
[email protected]7ef4cbbb2011-02-06 11:19:1011660 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1411661 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111662 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411663 if (rv == ERR_IO_PENDING)
11664 rv = callback.WaitForResult();
11665 EXPECT_EQ(OK, rv);
11666 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011667 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411668 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811669 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:3011670
[email protected]7ef4cbbb2011-02-06 11:19:1011671 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3011672 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111673 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3011674 if (rv == ERR_IO_PENDING)
11675 rv = callback.WaitForResult();
11676 EXPECT_EQ(OK, rv);
11677 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011678 ASSERT_TRUE(response != NULL);
[email protected]eca50e122010-09-11 14:03:3011679 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811680 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011681
11682 // Read the body since the fourth round was successful. This will also
11683 // release the socket back to the pool.
11684 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
[email protected]90499482013-06-01 00:39:5011685 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011686 if (rv == ERR_IO_PENDING)
11687 rv = callback.WaitForResult();
11688 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011689 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011690 EXPECT_EQ(0, rv);
11691 // There are still 0 idle sockets, since the trans_compete transaction
11692 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:2811693 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011694
11695 // The competing request can now finish. Wait for the headers and then
11696 // read the body.
11697 rv = callback_compete.WaitForResult();
11698 EXPECT_EQ(OK, rv);
[email protected]90499482013-06-01 00:39:5011699 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011700 if (rv == ERR_IO_PENDING)
11701 rv = callback.WaitForResult();
11702 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011703 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011704 EXPECT_EQ(0, rv);
11705
11706 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:2811707 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411708}
11709
[email protected]65041fa2010-05-21 06:56:5311710// This tests the case that a request is issued via http instead of spdy after
11711// npn is negotiated.
[email protected]23e482282013-06-14 16:08:0211712TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
bnc55ff9da2015-08-19 18:42:3511713 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311714 NextProtoVector next_protos;
[email protected]0ce3af82013-07-22 16:17:1611715 next_protos.push_back(kProtoHTTP11);
[email protected]d7599122014-05-24 03:37:2311716 session_deps_.next_protos = next_protos;
11717
[email protected]65041fa2010-05-21 06:56:5311718 HttpRequestInfo request;
11719 request.method = "GET";
bncce36dca22015-04-21 22:11:2311720 request.url = GURL("https://www.example.org/");
[email protected]65041fa2010-05-21 06:56:5311721 request.load_flags = 0;
11722
11723 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311724 MockWrite(
11725 "GET / HTTP/1.1\r\n"
11726 "Host: www.example.org\r\n"
11727 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5311728 };
11729
[email protected]8a0fc822013-06-27 20:52:4311730 std::string alternate_protocol_http_header =
11731 GetAlternateProtocolHttpHeader();
11732
[email protected]65041fa2010-05-21 06:56:5311733 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211734 MockRead("HTTP/1.1 200 OK\r\n"),
11735 MockRead(alternate_protocol_http_header.c_str()),
11736 MockRead("\r\n"),
11737 MockRead("hello world"),
11738 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5311739 };
11740
[email protected]8ddf8322012-02-23 18:08:0611741 SSLSocketDataProvider ssl(ASYNC, OK);
davidben6974bf72015-04-27 17:52:4811742 ssl.SetNextProto(kProtoHTTP11);
[email protected]65041fa2010-05-21 06:56:5311743
[email protected]bb88e1d32013-05-03 23:11:0711744 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5311745
11746 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11747 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0711748 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5311749
[email protected]49639fa2011-12-20 23:22:4111750 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5311751
mmenkee65e7af2015-10-13 17:16:4211752 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[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]65041fa2010-05-21 06:56:5311755
[email protected]49639fa2011-12-20 23:22:4111756 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]65041fa2010-05-21 06:56:5311757
11758 EXPECT_EQ(ERR_IO_PENDING, rv);
11759 EXPECT_EQ(OK, callback.WaitForResult());
11760
11761 const HttpResponseInfo* response = trans->GetResponseInfo();
11762 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011763 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]65041fa2010-05-21 06:56:5311764 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11765
11766 std::string response_data;
11767 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11768 EXPECT_EQ("hello world", response_data);
11769
11770 EXPECT_FALSE(response->was_fetched_via_spdy);
11771 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]65041fa2010-05-21 06:56:5311772}
[email protected]26ef6582010-06-24 02:30:4711773
bnc55ff9da2015-08-19 18:42:3511774// Simulate the SSL handshake completing with an NPN negotiation followed by an
11775// immediate server closing of the socket.
11776// Regression test for https://crbug.com/46369.
[email protected]23e482282013-06-14 16:08:0211777TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
bnc55ff9da2015-08-19 18:42:3511778 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311779 session_deps_.next_protos = SpdyNextProtos();
[email protected]26ef6582010-06-24 02:30:4711780
11781 HttpRequestInfo request;
11782 request.method = "GET";
bncce36dca22015-04-21 22:11:2311783 request.url = GURL("https://www.example.org/");
[email protected]26ef6582010-06-24 02:30:4711784 request.load_flags = 0;
11785
[email protected]8ddf8322012-02-23 18:08:0611786 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811787 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0711788 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4711789
[email protected]cdf8f7e72013-05-23 10:56:4611790 scoped_ptr<SpdyFrame> req(
11791 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1311792 MockWrite spdy_writes[] = {CreateMockWrite(*req, 1)};
[email protected]26ef6582010-06-24 02:30:4711793
11794 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0611795 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4711796 };
11797
rch8e6c6c42015-05-01 14:05:1311798 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11799 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711800 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4711801
[email protected]49639fa2011-12-20 23:22:4111802 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4711803
mmenkee65e7af2015-10-13 17:16:4211804 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3611805 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011806 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]26ef6582010-06-24 02:30:4711807
[email protected]49639fa2011-12-20 23:22:4111808 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]26ef6582010-06-24 02:30:4711809 EXPECT_EQ(ERR_IO_PENDING, rv);
11810 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
[email protected]26ef6582010-06-24 02:30:4711811}
[email protected]65d34382010-07-01 18:12:2611812
[email protected]795cbf82013-07-22 09:37:2711813// A subclass of HttpAuthHandlerMock that records the request URL when
11814// it gets it. This is needed since the auth handler may get destroyed
11815// before we get a chance to query it.
11816class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
11817 public:
11818 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
11819
dchengb03027d2014-10-21 12:00:2011820 ~UrlRecordingHttpAuthHandlerMock() override {}
[email protected]795cbf82013-07-22 09:37:2711821
11822 protected:
dchengb03027d2014-10-21 12:00:2011823 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
11824 const HttpRequestInfo* request,
11825 const CompletionCallback& callback,
11826 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2711827 *url_ = request->url;
11828 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
11829 credentials, request, callback, auth_token);
11830 }
11831
11832 private:
11833 GURL* url_;
11834};
11835
bnc55ff9da2015-08-19 18:42:3511836// This test ensures that the URL passed into the proxy is upgraded to https
11837// when doing an Alternate Protocol upgrade.
[email protected]23e482282013-06-14 16:08:0211838TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
bnc55ff9da2015-08-19 18:42:3511839 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311840 session_deps_.next_protos = SpdyNextProtos();
[email protected]f45c1ee2010-08-03 00:54:3011841
rdsmith82957ad2015-09-16 19:42:0311842 session_deps_.proxy_service =
11843 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5111844 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711845 session_deps_.net_log = &net_log;
[email protected]795cbf82013-07-22 09:37:2711846 GURL request_url;
11847 {
11848 HttpAuthHandlerMock::Factory* auth_factory =
11849 new HttpAuthHandlerMock::Factory();
11850 UrlRecordingHttpAuthHandlerMock* auth_handler =
11851 new UrlRecordingHttpAuthHandlerMock(&request_url);
11852 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
11853 auth_factory->set_do_init_from_challenge(true);
11854 session_deps_.http_auth_handler_factory.reset(auth_factory);
11855 }
[email protected]f45c1ee2010-08-03 00:54:3011856
11857 HttpRequestInfo request;
11858 request.method = "GET";
bncce36dca22015-04-21 22:11:2311859 request.url = GURL("http://www.example.org");
[email protected]f45c1ee2010-08-03 00:54:3011860 request.load_flags = 0;
11861
11862 // First round goes unauthenticated through the proxy.
11863 MockWrite data_writes_1[] = {
bncce36dca22015-04-21 22:11:2311864 MockWrite(
11865 "GET http://www.example.org/ HTTP/1.1\r\n"
11866 "Host: www.example.org\r\n"
11867 "Proxy-Connection: keep-alive\r\n"
11868 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011869 };
11870 MockRead data_reads_1[] = {
[email protected]8ddf8322012-02-23 18:08:0611871 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
bnc33b8cef42014-11-19 17:30:3811872 MockRead("HTTP/1.1 200 OK\r\n"),
11873 MockRead("Alternate-Protocol: 443:"),
11874 MockRead(GetAlternateProtocolFromParam()),
11875 MockRead("\r\n"),
11876 MockRead("Proxy-Connection: close\r\n"),
11877 MockRead("\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011878 };
11879 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
11880 data_writes_1, arraysize(data_writes_1));
11881
bncce36dca22015-04-21 22:11:2311882 // Second round tries to tunnel to www.example.org due to the
[email protected]f45c1ee2010-08-03 00:54:3011883 // Alternate-Protocol announcement in the first round. It fails due
11884 // to a proxy authentication challenge.
bncce36dca22015-04-21 22:11:2311885 // After the failure, a tunnel is established to www.example.org using
[email protected]394816e92010-08-03 07:38:5911886 // Proxy-Authorization headers. There is then a SPDY request round.
11887 //
[email protected]fe3b7dc2012-02-03 19:52:0911888 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
11889 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
11890 // does a Disconnect and Connect on the same socket, rather than trying
11891 // to obtain a new one.
11892 //
[email protected]394816e92010-08-03 07:38:5911893 // NOTE: Originally, the proxy response to the second CONNECT request
11894 // simply returned another 407 so the unit test could skip the SSL connection
11895 // establishment and SPDY framing issues. Alas, the
11896 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:3011897 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:5911898
[email protected]cdf8f7e72013-05-23 10:56:4611899 scoped_ptr<SpdyFrame> req(
11900 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]23e482282013-06-14 16:08:0211901 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11902 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]f45c1ee2010-08-03 00:54:3011903
[email protected]394816e92010-08-03 07:38:5911904 MockWrite data_writes_2[] = {
bncce36dca22015-04-21 22:11:2311905 // First connection attempt without Proxy-Authorization.
rch8e6c6c42015-05-01 14:05:1311906 MockWrite(ASYNC, 0,
11907 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711908 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1311909 "Proxy-Connection: keep-alive\r\n"
11910 "\r\n"),
[email protected]394816e92010-08-03 07:38:5911911
bncce36dca22015-04-21 22:11:2311912 // Second connection attempt with Proxy-Authorization.
rch8e6c6c42015-05-01 14:05:1311913 MockWrite(ASYNC, 2,
11914 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711915 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1311916 "Proxy-Connection: keep-alive\r\n"
11917 "Proxy-Authorization: auth_token\r\n"
11918 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011919
bncce36dca22015-04-21 22:11:2311920 // SPDY request
rch8e6c6c42015-05-01 14:05:1311921 CreateMockWrite(*req, 4),
[email protected]f45c1ee2010-08-03 00:54:3011922 };
[email protected]394816e92010-08-03 07:38:5911923 MockRead data_reads_2[] = {
rch8e6c6c42015-05-01 14:05:1311924 // First connection attempt fails
mmenkee71e15332015-10-07 16:39:5411925 MockRead(ASYNC, 1,
11926 "HTTP/1.1 407 Unauthorized\r\n"
11927 "Proxy-Authenticate: Mock\r\n"
11928 "Content-Length: 0\r\n"
11929 "Proxy-Connection: keep-alive\r\n"
11930 "\r\n"),
[email protected]394816e92010-08-03 07:38:5911931
rch8e6c6c42015-05-01 14:05:1311932 // Second connection attempt passes
mmenkee71e15332015-10-07 16:39:5411933 MockRead(ASYNC, 3, "HTTP/1.1 200 Connected\r\n\r\n"),
[email protected]394816e92010-08-03 07:38:5911934
rch8e6c6c42015-05-01 14:05:1311935 // SPDY response
mmenkee71e15332015-10-07 16:39:5411936 CreateMockRead(*resp.get(), 5), CreateMockRead(*data.get(), 6),
rch8e6c6c42015-05-01 14:05:1311937 MockRead(ASYNC, 0, 0, 7),
[email protected]394816e92010-08-03 07:38:5911938 };
rch8e6c6c42015-05-01 14:05:1311939 SequencedSocketData data_2(data_reads_2, arraysize(data_reads_2),
11940 data_writes_2, arraysize(data_writes_2));
[email protected]f45c1ee2010-08-03 00:54:3011941
[email protected]8ddf8322012-02-23 18:08:0611942 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811943 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2311944 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11945 ASSERT_TRUE(ssl.cert.get());
[email protected]f45c1ee2010-08-03 00:54:3011946
[email protected]d973e99a2012-02-17 21:02:3611947 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5511948 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
11949 NULL, 0, NULL, 0);
11950 hanging_non_alternate_protocol_socket.set_connect_data(
11951 never_finishing_connect);
11952
[email protected]bb88e1d32013-05-03 23:11:0711953 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
11954 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
11955 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11956 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5511957 &hanging_non_alternate_protocol_socket);
mmenkee65e7af2015-10-13 17:16:4211958 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f45c1ee2010-08-03 00:54:3011959
11960 // First round should work and provide the Alternate-Protocol state.
[email protected]49639fa2011-12-20 23:22:4111961 TestCompletionCallback callback_1;
[email protected]262eec82013-03-19 21:01:3611962 scoped_ptr<HttpTransaction> trans_1(
[email protected]90499482013-06-01 00:39:5011963 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111964 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:3011965 EXPECT_EQ(ERR_IO_PENDING, rv);
11966 EXPECT_EQ(OK, callback_1.WaitForResult());
11967
11968 // Second round should attempt a tunnel connect and get an auth challenge.
[email protected]49639fa2011-12-20 23:22:4111969 TestCompletionCallback callback_2;
[email protected]262eec82013-03-19 21:01:3611970 scoped_ptr<HttpTransaction> trans_2(
[email protected]90499482013-06-01 00:39:5011971 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111972 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:3011973 EXPECT_EQ(ERR_IO_PENDING, rv);
11974 EXPECT_EQ(OK, callback_2.WaitForResult());
11975 const HttpResponseInfo* response = trans_2->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011976 ASSERT_TRUE(response != NULL);
[email protected]f45c1ee2010-08-03 00:54:3011977 ASSERT_FALSE(response->auth_challenge.get() == NULL);
11978
11979 // Restart with auth. Tunnel should work and response received.
[email protected]49639fa2011-12-20 23:22:4111980 TestCompletionCallback callback_3;
11981 rv = trans_2->RestartWithAuth(
11982 AuthCredentials(kFoo, kBar), callback_3.callback());
[email protected]f45c1ee2010-08-03 00:54:3011983 EXPECT_EQ(ERR_IO_PENDING, rv);
11984 EXPECT_EQ(OK, callback_3.WaitForResult());
11985
11986 // After all that work, these two lines (or actually, just the scheme) are
11987 // what this test is all about. Make sure it happens correctly.
[email protected]f45c1ee2010-08-03 00:54:3011988 EXPECT_EQ("https", request_url.scheme());
bncce36dca22015-04-21 22:11:2311989 EXPECT_EQ("www.example.org", request_url.host());
[email protected]f45c1ee2010-08-03 00:54:3011990
[email protected]029c83b62013-01-24 05:28:2011991 LoadTimingInfo load_timing_info;
11992 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
11993 TestLoadTimingNotReusedWithPac(load_timing_info,
11994 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]8e6441ca2010-08-19 05:56:3811995}
11996
11997// Test that if we cancel the transaction as the connection is completing, that
11998// everything tears down correctly.
[email protected]23e482282013-06-14 16:08:0211999TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3812000 // Setup everything about the connection to complete synchronously, so that
12001 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
12002 // for is the callback from the HttpStreamRequest.
12003 // Then cancel the transaction.
12004 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3612005 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3812006 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0612007 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
12008 MockRead(SYNCHRONOUS, "hello world"),
12009 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3812010 };
12011
[email protected]8e6441ca2010-08-19 05:56:3812012 HttpRequestInfo request;
12013 request.method = "GET";
bncce36dca22015-04-21 22:11:2312014 request.url = GURL("http://www.example.org/");
[email protected]8e6441ca2010-08-19 05:56:3812015 request.load_flags = 0;
12016
[email protected]bb88e1d32013-05-03 23:11:0712017 session_deps_.host_resolver->set_synchronous_mode(true);
mmenkee65e7af2015-10-13 17:16:4212018 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:2712019 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4112020 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:2712021
[email protected]8e6441ca2010-08-19 05:56:3812022 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
12023 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712024 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3812025
[email protected]49639fa2011-12-20 23:22:4112026 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3812027
vishal.b62985ca92015-04-17 08:45:5112028 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4112029 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]8e6441ca2010-08-19 05:56:3812030 EXPECT_EQ(ERR_IO_PENDING, rv);
12031 trans.reset(); // Cancel the transaction here.
12032
[email protected]2da659e2013-05-23 20:51:3412033 base::MessageLoop::current()->RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3012034}
12035
[email protected]ecab6e052014-05-16 14:58:1212036// Test that if a transaction is cancelled after receiving the headers, the
12037// stream is drained properly and added back to the socket pool. The main
12038// purpose of this test is to make sure that an HttpStreamParser can be read
12039// from after the HttpNetworkTransaction and the objects it owns have been
12040// deleted.
12041// See http://crbug.com/368418
12042TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
12043 MockRead data_reads[] = {
12044 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
12045 MockRead(ASYNC, "Content-Length: 2\r\n"),
12046 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
12047 MockRead(ASYNC, "1"),
12048 // 2 async reads are necessary to trigger a ReadResponseBody call after the
12049 // HttpNetworkTransaction has been deleted.
12050 MockRead(ASYNC, "2"),
12051 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
12052 };
12053 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
12054 session_deps_.socket_factory->AddSocketDataProvider(&data);
12055
mmenkee65e7af2015-10-13 17:16:4212056 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1212057
12058 {
12059 HttpRequestInfo request;
12060 request.method = "GET";
bncce36dca22015-04-21 22:11:2312061 request.url = GURL("http://www.example.org/");
[email protected]ecab6e052014-05-16 14:58:1212062 request.load_flags = 0;
12063
dcheng48459ac22014-08-26 00:46:4112064 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1212065 TestCompletionCallback callback;
12066
12067 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
12068 EXPECT_EQ(ERR_IO_PENDING, rv);
12069 callback.WaitForResult();
12070
12071 const HttpResponseInfo* response = trans.GetResponseInfo();
12072 ASSERT_TRUE(response != NULL);
12073 EXPECT_TRUE(response->headers.get() != NULL);
12074 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12075
12076 // The transaction and HttpRequestInfo are deleted.
12077 }
12078
12079 // Let the HttpResponseBodyDrainer drain the socket.
12080 base::MessageLoop::current()->RunUntilIdle();
12081
12082 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4112083 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1212084}
12085
[email protected]76a505b2010-08-25 06:23:0012086// Test a basic GET request through a proxy.
[email protected]23e482282013-06-14 16:08:0212087TEST_P(HttpNetworkTransactionTest, ProxyGet) {
rdsmith82957ad2015-09-16 19:42:0312088 session_deps_.proxy_service =
12089 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112090 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712091 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4212092 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012093
[email protected]76a505b2010-08-25 06:23:0012094 HttpRequestInfo request;
12095 request.method = "GET";
bncce36dca22015-04-21 22:11:2312096 request.url = GURL("http://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012097
12098 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312099 MockWrite(
12100 "GET http://www.example.org/ HTTP/1.1\r\n"
12101 "Host: www.example.org\r\n"
12102 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012103 };
12104
12105 MockRead data_reads1[] = {
12106 MockRead("HTTP/1.1 200 OK\r\n"),
12107 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12108 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612109 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0012110 };
12111
12112 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12113 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712114 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0012115
[email protected]49639fa2011-12-20 23:22:4112116 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012117
[email protected]262eec82013-03-19 21:01:3612118 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012119 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]597a1ab2014-06-26 08:12:2712120 BeforeProxyHeadersSentHandler proxy_headers_handler;
12121 trans->SetBeforeProxyHeadersSentCallback(
12122 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
12123 base::Unretained(&proxy_headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5012124
[email protected]49639fa2011-12-20 23:22:4112125 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0012126 EXPECT_EQ(ERR_IO_PENDING, rv);
12127
12128 rv = callback1.WaitForResult();
12129 EXPECT_EQ(OK, rv);
12130
12131 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5012132 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:0012133
12134 EXPECT_TRUE(response->headers->IsKeepAlive());
12135 EXPECT_EQ(200, response->headers->response_code());
12136 EXPECT_EQ(100, response->headers->GetContentLength());
12137 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1512138 EXPECT_TRUE(
12139 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
[email protected]597a1ab2014-06-26 08:12:2712140 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
12141 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0012142 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2012143
12144 LoadTimingInfo load_timing_info;
12145 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12146 TestLoadTimingNotReusedWithPac(load_timing_info,
12147 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0012148}
12149
12150// Test a basic HTTPS GET request through a proxy.
[email protected]23e482282013-06-14 16:08:0212151TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
rdsmith82957ad2015-09-16 19:42:0312152 session_deps_.proxy_service =
12153 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112154 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712155 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4212156 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012157
[email protected]76a505b2010-08-25 06:23:0012158 HttpRequestInfo request;
12159 request.method = "GET";
bncce36dca22015-04-21 22:11:2312160 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012161
12162 // Since we have proxy, should try to establish tunnel.
12163 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1712164 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
12165 "Host: www.example.org:443\r\n"
12166 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012167
rsleevidb16bb02015-11-12 23:47:1712168 MockWrite("GET / HTTP/1.1\r\n"
12169 "Host: www.example.org\r\n"
12170 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012171 };
12172
12173 MockRead data_reads1[] = {
12174 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
12175
12176 MockRead("HTTP/1.1 200 OK\r\n"),
12177 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12178 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612179 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0012180 };
12181
12182 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12183 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712184 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0612185 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712186 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0012187
[email protected]49639fa2011-12-20 23:22:4112188 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012189
[email protected]262eec82013-03-19 21:01:3612190 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012191 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:5012192
[email protected]49639fa2011-12-20 23:22:4112193 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0012194 EXPECT_EQ(ERR_IO_PENDING, rv);
12195
12196 rv = callback1.WaitForResult();
12197 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:4612198 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4012199 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0012200 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012201 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0012202 NetLog::PHASE_NONE);
12203 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012204 entries, pos,
[email protected]76a505b2010-08-25 06:23:0012205 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12206 NetLog::PHASE_NONE);
12207
12208 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5012209 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:0012210
12211 EXPECT_TRUE(response->headers->IsKeepAlive());
12212 EXPECT_EQ(200, response->headers->response_code());
12213 EXPECT_EQ(100, response->headers->GetContentLength());
12214 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
12215 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1512216 EXPECT_TRUE(
12217 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
[email protected]029c83b62013-01-24 05:28:2012218
12219 LoadTimingInfo load_timing_info;
12220 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12221 TestLoadTimingNotReusedWithPac(load_timing_info,
12222 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0012223}
12224
rsleevidb16bb02015-11-12 23:47:1712225// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
12226// literal host.
12227TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
12228 session_deps_.proxy_service =
12229 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
12230 BoundTestNetLog log;
12231 session_deps_.net_log = log.bound().net_log();
12232 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12233
12234 HttpRequestInfo request;
12235 request.method = "GET";
12236 request.url = GURL("https://[::1]:443/");
12237
12238 // Since we have proxy, should try to establish tunnel.
12239 MockWrite data_writes1[] = {
12240 MockWrite("CONNECT [::1]:443 HTTP/1.1\r\n"
12241 "Host: [::1]:443\r\n"
12242 "Proxy-Connection: keep-alive\r\n\r\n"),
12243
12244 MockWrite("GET / HTTP/1.1\r\n"
12245 "Host: [::1]\r\n"
12246 "Connection: keep-alive\r\n\r\n"),
12247 };
12248
12249 MockRead data_reads1[] = {
12250 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
12251
12252 MockRead("HTTP/1.1 200 OK\r\n"),
12253 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12254 MockRead("Content-Length: 100\r\n\r\n"),
12255 MockRead(SYNCHRONOUS, OK),
12256 };
12257
12258 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12259 data_writes1, arraysize(data_writes1));
12260 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12261 SSLSocketDataProvider ssl(ASYNC, OK);
12262 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12263
12264 TestCompletionCallback callback1;
12265
12266 scoped_ptr<HttpTransaction> trans(
12267 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12268
12269 int rv = trans->Start(&request, callback1.callback(), log.bound());
12270 EXPECT_EQ(ERR_IO_PENDING, rv);
12271
12272 rv = callback1.WaitForResult();
12273 EXPECT_EQ(OK, rv);
12274 TestNetLogEntry::List entries;
12275 log.GetEntries(&entries);
12276 size_t pos = ExpectLogContainsSomewhere(
12277 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
12278 NetLog::PHASE_NONE);
12279 ExpectLogContainsSomewhere(
12280 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12281 NetLog::PHASE_NONE);
12282
12283 const HttpResponseInfo* response = trans->GetResponseInfo();
12284 ASSERT_TRUE(response != NULL);
12285
12286 EXPECT_TRUE(response->headers->IsKeepAlive());
12287 EXPECT_EQ(200, response->headers->response_code());
12288 EXPECT_EQ(100, response->headers->GetContentLength());
12289 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
12290 EXPECT_TRUE(response->was_fetched_via_proxy);
12291 EXPECT_TRUE(
12292 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
12293
12294 LoadTimingInfo load_timing_info;
12295 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12296 TestLoadTimingNotReusedWithPac(load_timing_info,
12297 CONNECT_TIMING_HAS_SSL_TIMES);
12298}
12299
[email protected]76a505b2010-08-25 06:23:0012300// Test a basic HTTPS GET request through a proxy, but the server hangs up
12301// while establishing the tunnel.
[email protected]23e482282013-06-14 16:08:0212302TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
rdsmith82957ad2015-09-16 19:42:0312303 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112304 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712305 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4212306 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012307
[email protected]76a505b2010-08-25 06:23:0012308 HttpRequestInfo request;
12309 request.method = "GET";
bncce36dca22015-04-21 22:11:2312310 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012311
12312 // Since we have proxy, should try to establish tunnel.
12313 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1712314 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
12315 "Host: www.example.org:443\r\n"
12316 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012317
rsleevidb16bb02015-11-12 23:47:1712318 MockWrite("GET / HTTP/1.1\r\n"
12319 "Host: www.example.org\r\n"
12320 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012321 };
12322
12323 MockRead data_reads1[] = {
[email protected]8ddf8322012-02-23 18:08:0612324 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]76a505b2010-08-25 06:23:0012325 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612326 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0012327 };
12328
12329 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12330 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712331 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0612332 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712333 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0012334
[email protected]49639fa2011-12-20 23:22:4112335 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012336
[email protected]262eec82013-03-19 21:01:3612337 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012338 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:5012339
[email protected]49639fa2011-12-20 23:22:4112340 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0012341 EXPECT_EQ(ERR_IO_PENDING, rv);
12342
12343 rv = callback1.WaitForResult();
12344 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
mmenke43758e62015-05-04 21:09:4612345 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4012346 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0012347 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012348 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0012349 NetLog::PHASE_NONE);
12350 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012351 entries, pos,
[email protected]76a505b2010-08-25 06:23:0012352 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12353 NetLog::PHASE_NONE);
12354}
12355
[email protected]749eefa82010-09-13 22:14:0312356// Test for crbug.com/55424.
[email protected]23e482282013-06-14 16:08:0212357TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
[email protected]cdf8f7e72013-05-23 10:56:4612358 scoped_ptr<SpdyFrame> req(
bncce36dca22015-04-21 22:11:2312359 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rch8e6c6c42015-05-01 14:05:1312360 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]749eefa82010-09-13 22:14:0312361
[email protected]23e482282013-06-14 16:08:0212362 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12363 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0312364 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312365 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0312366 };
12367
rch8e6c6c42015-05-01 14:05:1312368 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
12369 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712370 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0312371
[email protected]8ddf8322012-02-23 18:08:0612372 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812373 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712374 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0312375
mmenkee65e7af2015-10-13 17:16:4212376 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0312377
12378 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2312379 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4012380 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5312381 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2712382 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:4212383 CreateInsecureSpdySession(session.get(), key, BoundNetLog());
[email protected]749eefa82010-09-13 22:14:0312384
12385 HttpRequestInfo request;
12386 request.method = "GET";
bncce36dca22015-04-21 22:11:2312387 request.url = GURL("https://www.example.org/");
[email protected]749eefa82010-09-13 22:14:0312388 request.load_flags = 0;
12389
12390 // This is the important line that marks this as a preconnect.
12391 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
12392
[email protected]262eec82013-03-19 21:01:3612393 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012394 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]749eefa82010-09-13 22:14:0312395
[email protected]41d64e82013-07-03 22:44:2612396 TestCompletionCallback callback;
[email protected]49639fa2011-12-20 23:22:4112397 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]749eefa82010-09-13 22:14:0312398 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112399 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]749eefa82010-09-13 22:14:0312400}
12401
[email protected]73b8dd222010-11-11 19:55:2412402// Given a net error, cause that error to be returned from the first Write()
12403// call and verify that the HttpTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0212404void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0712405 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2912406 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712407 request_info.url = GURL("https://www.example.com/");
12408 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912409 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712410
[email protected]8ddf8322012-02-23 18:08:0612411 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2912412 MockWrite data_writes[] = {
12413 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2412414 };
ttuttle859dc7a2015-04-23 19:42:2912415 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0712416 session_deps_.socket_factory->AddSocketDataProvider(&data);
12417 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2412418
mmenkee65e7af2015-10-13 17:16:4212419 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612420 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012421 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]73b8dd222010-11-11 19:55:2412422
[email protected]49639fa2011-12-20 23:22:4112423 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912424 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12425 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2412426 rv = callback.WaitForResult();
12427 ASSERT_EQ(error, rv);
12428}
12429
[email protected]23e482282013-06-14 16:08:0212430TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2412431 // Just check a grab bag of cert errors.
12432 static const int kErrors[] = {
12433 ERR_CERT_COMMON_NAME_INVALID,
12434 ERR_CERT_AUTHORITY_INVALID,
12435 ERR_CERT_DATE_INVALID,
12436 };
12437 for (size_t i = 0; i < arraysize(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0612438 CheckErrorIsPassedBack(kErrors[i], ASYNC);
12439 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2412440 }
12441}
12442
[email protected]bd0b6772011-01-11 19:59:3012443// Ensure that a client certificate is removed from the SSL client auth
12444// cache when:
12445// 1) No proxy is involved.
12446// 2) TLS False Start is disabled.
12447// 3) The initial TLS handshake requests a client certificate.
12448// 4) The client supplies an invalid/unacceptable certificate.
[email protected]23e482282013-06-14 16:08:0212449TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2312450 ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912451 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712452 request_info.url = GURL("https://www.example.com/");
12453 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912454 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712455
[email protected]bd0b6772011-01-11 19:59:3012456 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112457 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012458
12459 // [ssl_]data1 contains the data for the first SSL handshake. When a
12460 // CertificateRequest is received for the first time, the handshake will
12461 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2912462 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012463 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712464 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912465 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712466 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012467
12468 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
12469 // False Start is not being used, the result of the SSL handshake will be
12470 // returned as part of the SSLClientSocket::Connect() call. This test
12471 // matches the result of a server sending a handshake_failure alert,
12472 // rather than a Finished message, because it requires a client
12473 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2912474 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012475 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712476 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912477 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712478 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012479
12480 // [ssl_]data3 contains the data for the third SSL handshake. When a
12481 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212482 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
12483 // connection was attempted with TLSv1.2. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3012484 // of the HttpNetworkTransaction. Because this test failure is due to
12485 // requiring a client certificate, this fallback handshake should also
12486 // fail.
ttuttle859dc7a2015-04-23 19:42:2912487 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012488 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712489 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912490 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712491 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012492
[email protected]80c75f682012-05-26 16:22:1712493 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
12494 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212495 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
12496 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1712497 // of the HttpNetworkTransaction. Because this test failure is due to
12498 // requiring a client certificate, this fallback handshake should also
12499 // fail.
ttuttle859dc7a2015-04-23 19:42:2912500 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1712501 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712502 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912503 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712504 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712505
mmenkee65e7af2015-10-13 17:16:4212506 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612507 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012508 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012509
[email protected]bd0b6772011-01-11 19:59:3012510 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4112511 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912512 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12513 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012514
12515 // Complete the SSL handshake, which should abort due to requiring a
12516 // client certificate.
12517 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912518 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]bd0b6772011-01-11 19:59:3012519
12520 // Indicate that no certificate should be supplied. From the perspective
12521 // of SSLClientCertCache, NULL is just as meaningful as a real
12522 // certificate, so this is the same as supply a
12523 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412524 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912525 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012526
12527 // Ensure the certificate was added to the client auth cache before
12528 // allowing the connection to continue restarting.
12529 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412530 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112531 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412532 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012533 ASSERT_EQ(NULL, client_cert.get());
12534
12535 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712536 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12537 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012538 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912539 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
[email protected]bd0b6772011-01-11 19:59:3012540
12541 // Ensure that the client certificate is removed from the cache on a
12542 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112543 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412544 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012545}
12546
12547// Ensure that a client certificate is removed from the SSL client auth
12548// cache when:
12549// 1) No proxy is involved.
12550// 2) TLS False Start is enabled.
12551// 3) The initial TLS handshake requests a client certificate.
12552// 4) The client supplies an invalid/unacceptable certificate.
[email protected]23e482282013-06-14 16:08:0212553TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2312554 ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912555 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712556 request_info.url = GURL("https://www.example.com/");
12557 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912558 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712559
[email protected]bd0b6772011-01-11 19:59:3012560 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112561 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012562
12563 // When TLS False Start is used, SSLClientSocket::Connect() calls will
12564 // return successfully after reading up to the peer's Certificate message.
12565 // This is to allow the caller to call SSLClientSocket::Write(), which can
12566 // enqueue application data to be sent in the same packet as the
12567 // ChangeCipherSpec and Finished messages.
12568 // The actual handshake will be finished when SSLClientSocket::Read() is
12569 // called, which expects to process the peer's ChangeCipherSpec and
12570 // Finished messages. If there was an error negotiating with the peer,
12571 // such as due to the peer requiring a client certificate when none was
12572 // supplied, the alert sent by the peer won't be processed until Read() is
12573 // called.
12574
12575 // Like the non-False Start case, when a client certificate is requested by
12576 // the peer, the handshake is aborted during the Connect() call.
12577 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2912578 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012579 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712580 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912581 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712582 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012583
12584 // When a client certificate is supplied, Connect() will not be aborted
12585 // when the peer requests the certificate. Instead, the handshake will
12586 // artificially succeed, allowing the caller to write the HTTP request to
12587 // the socket. The handshake messages are not processed until Read() is
12588 // called, which then detects that the handshake was aborted, due to the
12589 // peer sending a handshake_failure because it requires a client
12590 // certificate.
ttuttle859dc7a2015-04-23 19:42:2912591 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012592 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712593 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912594 MockRead data2_reads[] = {
12595 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3012596 };
ttuttle859dc7a2015-04-23 19:42:2912597 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712598 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012599
12600 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1712601 // the data for the SSL handshake once the TLSv1.1 connection falls back to
12602 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912603 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012604 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712605 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912606 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712607 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012608
[email protected]80c75f682012-05-26 16:22:1712609 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
12610 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912611 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1712612 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712613 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912614 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712615 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712616
[email protected]7799de12013-05-30 05:52:5112617 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2912618 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5112619 ssl_data5.cert_request_info = cert_request.get();
12620 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
ttuttle859dc7a2015-04-23 19:42:2912621 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]7799de12013-05-30 05:52:5112622 session_deps_.socket_factory->AddSocketDataProvider(&data5);
12623
mmenkee65e7af2015-10-13 17:16:4212624 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612625 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012626 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012627
[email protected]bd0b6772011-01-11 19:59:3012628 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4112629 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912630 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12631 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012632
12633 // Complete the SSL handshake, which should abort due to requiring a
12634 // client certificate.
12635 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912636 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]bd0b6772011-01-11 19:59:3012637
12638 // Indicate that no certificate should be supplied. From the perspective
12639 // of SSLClientCertCache, NULL is just as meaningful as a real
12640 // certificate, so this is the same as supply a
12641 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412642 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912643 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012644
12645 // Ensure the certificate was added to the client auth cache before
12646 // allowing the connection to continue restarting.
12647 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412648 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112649 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412650 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012651 ASSERT_EQ(NULL, client_cert.get());
12652
[email protected]bd0b6772011-01-11 19:59:3012653 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712654 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12655 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012656 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912657 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
[email protected]bd0b6772011-01-11 19:59:3012658
12659 // Ensure that the client certificate is removed from the cache on a
12660 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112661 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412662 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012663}
12664
[email protected]8c405132011-01-11 22:03:1812665// Ensure that a client certificate is removed from the SSL client auth
12666// cache when:
12667// 1) An HTTPS proxy is involved.
12668// 3) The HTTPS proxy requests a client certificate.
12669// 4) The client supplies an invalid/unacceptable certificate for the
12670// proxy.
12671// The test is repeated twice, first for connecting to an HTTPS endpoint,
12672// then for connecting to an HTTP endpoint.
[email protected]23e482282013-06-14 16:08:0212673TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
rdsmith82957ad2015-09-16 19:42:0312674 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:5112675 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712676 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1812677
12678 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112679 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1812680
12681 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
12682 // [ssl_]data[1-3]. Rather than represending the endpoint
12683 // (www.example.com:443), they represent failures with the HTTPS proxy
12684 // (proxy:70).
ttuttle859dc7a2015-04-23 19:42:2912685 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8c405132011-01-11 22:03:1812686 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712687 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912688 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712689 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1812690
ttuttle859dc7a2015-04-23 19:42:2912691 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812692 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712693 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912694 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712695 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8c405132011-01-11 22:03:1812696
[email protected]80c75f682012-05-26 16:22:1712697 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
12698#if 0
ttuttle859dc7a2015-04-23 19:42:2912699 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812700 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712701 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912702 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712703 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]80c75f682012-05-26 16:22:1712704#endif
[email protected]8c405132011-01-11 22:03:1812705
ttuttle859dc7a2015-04-23 19:42:2912706 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1812707 requests[0].url = GURL("https://www.example.com/");
12708 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912709 requests[0].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812710
12711 requests[1].url = GURL("http://www.example.com/");
12712 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912713 requests[1].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812714
12715 for (size_t i = 0; i < arraysize(requests); ++i) {
[email protected]bb88e1d32013-05-03 23:11:0712716 session_deps_.socket_factory->ResetNextMockIndexes();
mmenkee65e7af2015-10-13 17:16:4212717 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c405132011-01-11 22:03:1812718 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5012719 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c405132011-01-11 22:03:1812720
12721 // Begin the SSL handshake with the proxy.
[email protected]49639fa2011-12-20 23:22:4112722 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912723 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
12724 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]8c405132011-01-11 22:03:1812725
12726 // Complete the SSL handshake, which should abort due to requiring a
12727 // client certificate.
12728 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912729 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]8c405132011-01-11 22:03:1812730
12731 // Indicate that no certificate should be supplied. From the perspective
12732 // of SSLClientCertCache, NULL is just as meaningful as a real
12733 // certificate, so this is the same as supply a
12734 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412735 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912736 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]8c405132011-01-11 22:03:1812737
12738 // Ensure the certificate was added to the client auth cache before
12739 // allowing the connection to continue restarting.
12740 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412741 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112742 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412743 HostPortPair("proxy", 70), &client_cert, &client_private_key));
[email protected]8c405132011-01-11 22:03:1812744 ASSERT_EQ(NULL, client_cert.get());
12745 // Ensure the certificate was NOT cached for the endpoint. This only
12746 // applies to HTTPS requests, but is fine to check for HTTP requests.
[email protected]791879c2013-12-17 07:22:4112747 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412748 HostPortPair("www.example.com", 443), &client_cert,
12749 &client_private_key));
[email protected]8c405132011-01-11 22:03:1812750
12751 // Restart the handshake. This will consume ssl_data2, which fails, and
12752 // then consume ssl_data3, which should also fail. The result code is
12753 // checked against what ssl_data3 should return.
12754 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912755 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]8c405132011-01-11 22:03:1812756
12757 // Now that the new handshake has failed, ensure that the client
12758 // certificate was removed from the client auth cache.
[email protected]791879c2013-12-17 07:22:4112759 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412760 HostPortPair("proxy", 70), &client_cert, &client_private_key));
[email protected]791879c2013-12-17 07:22:4112761 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412762 HostPortPair("www.example.com", 443), &client_cert,
12763 &client_private_key));
[email protected]8c405132011-01-11 22:03:1812764 }
12765}
12766
mmenke5c642132015-06-02 16:05:1312767TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
bnc55ff9da2015-08-19 18:42:3512768 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312769 session_deps_.next_protos = SpdyNextProtos();
[email protected]e3ceb682011-06-28 23:55:4612770
12771 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712772 session_deps_.host_resolver.reset(new MockCachingHostResolver());
mmenkee65e7af2015-10-13 17:16:4212773 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2612774 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12775 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4612776
[email protected]8ddf8322012-02-23 18:08:0612777 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812778 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712779 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4612780
[email protected]cdf8f7e72013-05-23 10:56:4612781 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2312782 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812783 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4612784 scoped_ptr<SpdyFrame> host2_req(
12785 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4612786 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312787 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4612788 };
[email protected]23e482282013-06-14 16:08:0212789 scoped_ptr<SpdyFrame> host1_resp(
12790 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12791 scoped_ptr<SpdyFrame> host1_resp_body(
12792 spdy_util_.ConstructSpdyBodyFrame(1, true));
12793 scoped_ptr<SpdyFrame> host2_resp(
12794 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12795 scoped_ptr<SpdyFrame> host2_resp_body(
12796 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4612797 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312798 CreateMockRead(*host1_resp, 1),
12799 CreateMockRead(*host1_resp_body, 2),
12800 CreateMockRead(*host2_resp, 4),
12801 CreateMockRead(*host2_resp_body, 5),
12802 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4612803 };
12804
[email protected]d2b5f092012-06-08 23:55:0212805 IPAddressNumber ip;
12806 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
12807 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12808 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312809 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12810 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712811 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4612812
[email protected]aa22b242011-11-16 18:58:2912813 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4612814 HttpRequestInfo request1;
12815 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312816 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4612817 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012818 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612819
[email protected]49639fa2011-12-20 23:22:4112820 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612821 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112822 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612823
12824 const HttpResponseInfo* response = trans1.GetResponseInfo();
12825 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012826 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212827 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612828
12829 std::string response_data;
12830 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12831 EXPECT_EQ("hello!", response_data);
12832
12833 // Preload www.gmail.com into HostCache.
12834 HostPortPair host_port("www.gmail.com", 443);
[email protected]5109c1952013-08-20 18:44:1012835 HostResolver::RequestInfo resolve_info(host_port);
[email protected]e3ceb682011-06-28 23:55:4612836 AddressList ignored;
[email protected]5109c1952013-08-20 18:44:1012837 rv = session_deps_.host_resolver->Resolve(resolve_info,
12838 DEFAULT_PRIORITY,
12839 &ignored,
12840 callback.callback(),
12841 NULL,
12842 BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:4712843 EXPECT_EQ(ERR_IO_PENDING, rv);
12844 rv = callback.WaitForResult();
12845 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:4612846
12847 HttpRequestInfo request2;
12848 request2.method = "GET";
12849 request2.url = GURL("https://www.gmail.com/");
12850 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012851 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612852
[email protected]49639fa2011-12-20 23:22:4112853 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612854 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112855 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612856
12857 response = trans2.GetResponseInfo();
12858 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012859 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212860 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612861 EXPECT_TRUE(response->was_fetched_via_spdy);
12862 EXPECT_TRUE(response->was_npn_negotiated);
12863 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12864 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4612865}
12866
[email protected]23e482282013-06-14 16:08:0212867TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
bnc55ff9da2015-08-19 18:42:3512868 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312869 session_deps_.next_protos = SpdyNextProtos();
[email protected]d2b5f092012-06-08 23:55:0212870
12871 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712872 session_deps_.host_resolver.reset(new MockCachingHostResolver());
mmenkee65e7af2015-10-13 17:16:4212873 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0212874 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12875 pool_peer.DisableDomainAuthenticationVerification();
12876
12877 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812878 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712879 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]d2b5f092012-06-08 23:55:0212880
[email protected]cdf8f7e72013-05-23 10:56:4612881 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2312882 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812883 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4612884 scoped_ptr<SpdyFrame> host2_req(
12885 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0212886 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312887 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0212888 };
[email protected]23e482282013-06-14 16:08:0212889 scoped_ptr<SpdyFrame> host1_resp(
12890 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12891 scoped_ptr<SpdyFrame> host1_resp_body(
12892 spdy_util_.ConstructSpdyBodyFrame(1, true));
12893 scoped_ptr<SpdyFrame> host2_resp(
12894 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12895 scoped_ptr<SpdyFrame> host2_resp_body(
12896 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0212897 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312898 CreateMockRead(*host1_resp, 1),
12899 CreateMockRead(*host1_resp_body, 2),
12900 CreateMockRead(*host2_resp, 4),
12901 CreateMockRead(*host2_resp_body, 5),
12902 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0212903 };
12904
12905 IPAddressNumber ip;
12906 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
12907 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12908 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312909 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12910 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712911 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0212912
12913 TestCompletionCallback callback;
12914 HttpRequestInfo request1;
12915 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312916 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0212917 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012918 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0212919
12920 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
12921 EXPECT_EQ(ERR_IO_PENDING, rv);
12922 EXPECT_EQ(OK, callback.WaitForResult());
12923
12924 const HttpResponseInfo* response = trans1.GetResponseInfo();
12925 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012926 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212927 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0212928
12929 std::string response_data;
12930 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12931 EXPECT_EQ("hello!", response_data);
12932
12933 HttpRequestInfo request2;
12934 request2.method = "GET";
12935 request2.url = GURL("https://www.gmail.com/");
12936 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012937 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0212938
12939 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
12940 EXPECT_EQ(ERR_IO_PENDING, rv);
12941 EXPECT_EQ(OK, callback.WaitForResult());
12942
12943 response = trans2.GetResponseInfo();
12944 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012945 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212946 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0212947 EXPECT_TRUE(response->was_fetched_via_spdy);
12948 EXPECT_TRUE(response->was_npn_negotiated);
12949 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12950 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0212951}
12952
ttuttle859dc7a2015-04-23 19:42:2912953class OneTimeCachingHostResolver : public HostResolver {
[email protected]e3ceb682011-06-28 23:55:4612954 public:
12955 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
12956 : host_port_(host_port) {}
dchengb03027d2014-10-21 12:00:2012957 ~OneTimeCachingHostResolver() override {}
[email protected]e3ceb682011-06-28 23:55:4612958
12959 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
12960
12961 // HostResolver methods:
dchengb03027d2014-10-21 12:00:2012962 int Resolve(const RequestInfo& info,
12963 RequestPriority priority,
12964 AddressList* addresses,
12965 const CompletionCallback& callback,
12966 RequestHandle* out_req,
12967 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4012968 return host_resolver_.Resolve(
[email protected]5109c1952013-08-20 18:44:1012969 info, priority, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:4012970 }
12971
dchengb03027d2014-10-21 12:00:2012972 int ResolveFromCache(const RequestInfo& info,
12973 AddressList* addresses,
12974 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4012975 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
12976 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]98e1cd012011-11-08 15:33:0912977 host_resolver_.GetHostCache()->clear();
[email protected]e3ceb682011-06-28 23:55:4612978 return rv;
12979 }
12980
dchengb03027d2014-10-21 12:00:2012981 void CancelRequest(RequestHandle req) override {
[email protected]e3ceb682011-06-28 23:55:4612982 host_resolver_.CancelRequest(req);
12983 }
12984
[email protected]46da33be2011-07-19 21:58:0412985 MockCachingHostResolver* GetMockHostResolver() {
12986 return &host_resolver_;
12987 }
12988
[email protected]e3ceb682011-06-28 23:55:4612989 private:
12990 MockCachingHostResolver host_resolver_;
12991 const HostPortPair host_port_;
12992};
12993
mmenke5c642132015-06-02 16:05:1312994TEST_P(HttpNetworkTransactionTest,
12995 UseIPConnectionPoolingWithHostCacheExpiration) {
bnc55ff9da2015-08-19 18:42:3512996 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312997 session_deps_.next_protos = SpdyNextProtos();
[email protected]e3ceb682011-06-28 23:55:4612998
12999 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
[email protected]e3ceb682011-06-28 23:55:4613000 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
[email protected]c6bf8152012-12-02 07:43:3413001 HttpNetworkSession::Params params =
[email protected]bb88e1d32013-05-03 23:11:0713002 SpdySessionDependencies::CreateSessionParams(&session_deps_);
[email protected]e3ceb682011-06-28 23:55:4613003 params.host_resolver = &host_resolver;
mmenkee65e7af2015-10-13 17:16:4213004 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2613005 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
13006 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4613007
[email protected]8ddf8322012-02-23 18:08:0613008 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813009 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713010 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4613011
[email protected]cdf8f7e72013-05-23 10:56:4613012 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2313013 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3813014 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4613015 scoped_ptr<SpdyFrame> host2_req(
13016 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4613017 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1313018 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4613019 };
[email protected]23e482282013-06-14 16:08:0213020 scoped_ptr<SpdyFrame> host1_resp(
13021 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13022 scoped_ptr<SpdyFrame> host1_resp_body(
13023 spdy_util_.ConstructSpdyBodyFrame(1, true));
13024 scoped_ptr<SpdyFrame> host2_resp(
13025 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13026 scoped_ptr<SpdyFrame> host2_resp_body(
13027 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4613028 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1313029 CreateMockRead(*host1_resp, 1),
13030 CreateMockRead(*host1_resp_body, 2),
13031 CreateMockRead(*host2_resp, 4),
13032 CreateMockRead(*host2_resp_body, 5),
13033 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4613034 };
13035
[email protected]d2b5f092012-06-08 23:55:0213036 IPAddressNumber ip;
13037 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
13038 IPEndPoint peer_addr = IPEndPoint(ip, 443);
13039 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1313040 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
13041 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0713042 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4613043
[email protected]aa22b242011-11-16 18:58:2913044 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4613045 HttpRequestInfo request1;
13046 request1.method = "GET";
bncce36dca22015-04-21 22:11:2313047 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4613048 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013049 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4613050
[email protected]49639fa2011-12-20 23:22:4113051 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4613052 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4113053 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4613054
13055 const HttpResponseInfo* response = trans1.GetResponseInfo();
13056 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013057 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0213058 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4613059
13060 std::string response_data;
13061 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
13062 EXPECT_EQ("hello!", response_data);
13063
13064 // Preload cache entries into HostCache.
[email protected]5109c1952013-08-20 18:44:1013065 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
[email protected]e3ceb682011-06-28 23:55:4613066 AddressList ignored;
[email protected]5109c1952013-08-20 18:44:1013067 rv = host_resolver.Resolve(resolve_info,
13068 DEFAULT_PRIORITY,
13069 &ignored,
13070 callback.callback(),
13071 NULL,
13072 BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:4713073 EXPECT_EQ(ERR_IO_PENDING, rv);
13074 rv = callback.WaitForResult();
13075 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:4613076
13077 HttpRequestInfo request2;
13078 request2.method = "GET";
13079 request2.url = GURL("https://www.gmail.com/");
13080 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013081 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4613082
[email protected]49639fa2011-12-20 23:22:4113083 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4613084 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4113085 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4613086
13087 response = trans2.GetResponseInfo();
13088 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013089 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0213090 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4613091 EXPECT_TRUE(response->was_fetched_via_spdy);
13092 EXPECT_TRUE(response->was_npn_negotiated);
13093 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
13094 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4613095}
13096
[email protected]23e482282013-06-14 16:08:0213097TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2313098 const std::string https_url = "https://www.example.org:8080/";
13099 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0413100
13101 // SPDY GET for HTTPS URL
[email protected]cdf8f7e72013-05-23 10:56:4613102 scoped_ptr<SpdyFrame> req1(
13103 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0413104
13105 MockWrite writes1[] = {
13106 CreateMockWrite(*req1, 0),
13107 };
13108
[email protected]23e482282013-06-14 16:08:0213109 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13110 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
mmenkee24011922015-12-17 22:12:5913111 MockRead reads1[] = {CreateMockRead(*resp1, 1), CreateMockRead(*body1, 2),
13112 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0413113
rch8e6c6c42015-05-01 14:05:1313114 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
13115 arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0413116 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5713117 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0413118
13119 // HTTP GET for the HTTP URL
13120 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1313121 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3413122 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2313123 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3413124 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0413125 };
13126
13127 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1313128 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
13129 MockRead(ASYNC, 2, "hello"),
13130 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0413131 };
13132
rch8e6c6c42015-05-01 14:05:1313133 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13134 arraysize(writes2));
[email protected]8450d722012-07-02 19:14:0413135
[email protected]8450d722012-07-02 19:14:0413136 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813137 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713138 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13139 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13140 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0413141
mmenkee65e7af2015-10-13 17:16:4213142 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0413143
13144 // Start the first transaction to set up the SpdySession
13145 HttpRequestInfo request1;
13146 request1.method = "GET";
13147 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0413148 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013149 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0413150 TestCompletionCallback callback1;
13151 EXPECT_EQ(ERR_IO_PENDING,
13152 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413153 base::MessageLoop::current()->RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0413154
13155 EXPECT_EQ(OK, callback1.WaitForResult());
13156 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13157
13158 // Now, start the HTTP request
13159 HttpRequestInfo request2;
13160 request2.method = "GET";
13161 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0413162 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013163 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0413164 TestCompletionCallback callback2;
13165 EXPECT_EQ(ERR_IO_PENDING,
13166 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413167 base::MessageLoop::current()->RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0413168
13169 EXPECT_EQ(OK, callback2.WaitForResult());
13170 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13171}
13172
bnc1b0e36852015-04-28 15:32:5913173class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
13174 public:
13175 void Run(bool pooling, bool valid) {
13176 HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org",
13177 443);
13178 HostPortPair alternative("www.example.org", 443);
13179
13180 base::FilePath certs_dir = GetTestCertsDirectory();
13181 scoped_refptr<X509Certificate> cert(
13182 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
13183 ASSERT_TRUE(cert.get());
13184 bool common_name_fallback_used;
13185 EXPECT_EQ(valid,
13186 cert->VerifyNameMatch(origin.host(), &common_name_fallback_used));
13187 EXPECT_TRUE(
13188 cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used));
13189 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813190 ssl.SetNextProto(GetProtocol());
bnc1b0e36852015-04-28 15:32:5913191 ssl.cert = cert;
13192 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13193
13194 // If pooling, then start a request to alternative first to create a
13195 // SpdySession.
13196 std::string url0 = "https://www.example.org:443";
13197 // Second request to origin, which has an alternative service, and could
13198 // open a connection to the alternative host or pool to the existing one.
13199 std::string url1("https://");
13200 url1.append(origin.host());
13201 url1.append(":443");
13202
13203 scoped_ptr<SpdyFrame> req0;
13204 scoped_ptr<SpdyFrame> req1;
13205 scoped_ptr<SpdyFrame> resp0;
13206 scoped_ptr<SpdyFrame> body0;
13207 scoped_ptr<SpdyFrame> resp1;
13208 scoped_ptr<SpdyFrame> body1;
13209 std::vector<MockWrite> writes;
13210 std::vector<MockRead> reads;
13211
13212 if (pooling) {
13213 req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3813214 spdy_util_.UpdateWithStreamDestruction(1);
bnc1b0e36852015-04-28 15:32:5913215 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 3, LOWEST));
13216
13217 writes.push_back(CreateMockWrite(*req0, 0));
13218 writes.push_back(CreateMockWrite(*req1, 3));
13219
13220 resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13221 body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
13222 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13223 body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true));
13224
13225 reads.push_back(CreateMockRead(*resp0, 1));
13226 reads.push_back(CreateMockRead(*body0, 2));
13227 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4));
13228 reads.push_back(CreateMockRead(*resp1, 5));
13229 reads.push_back(CreateMockRead(*body1, 6));
13230 reads.push_back(MockRead(ASYNC, OK, 7));
13231 } else {
13232 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 1, LOWEST));
13233
13234 writes.push_back(CreateMockWrite(*req1, 0));
13235
13236 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13237 body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
13238
13239 reads.push_back(CreateMockRead(*resp1, 1));
13240 reads.push_back(CreateMockRead(*body1, 2));
13241 reads.push_back(MockRead(ASYNC, OK, 3));
13242 }
13243
davidben5f8b6bc2015-11-25 03:19:5413244 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
13245 writes.size());
bnc1b0e36852015-04-28 15:32:5913246 session_deps_.socket_factory->AddSocketDataProvider(&data);
13247
13248 // Connection to the origin fails.
13249 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13250 StaticSocketDataProvider data_refused;
13251 data_refused.set_connect_data(mock_connect);
13252 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13253
bnc55ff9da2015-08-19 18:42:3513254 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213255 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc1b0e36852015-04-28 15:32:5913256 base::WeakPtr<HttpServerProperties> http_server_properties =
13257 session->http_server_properties();
13258 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813259 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213260 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc1b0e36852015-04-28 15:32:5913261 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213262 1.0, expiration);
bnc1b0e36852015-04-28 15:32:5913263
13264 // First request to alternative.
13265 if (pooling) {
13266 scoped_ptr<HttpTransaction> trans0(
13267 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13268 HttpRequestInfo request0;
13269 request0.method = "GET";
13270 request0.url = GURL(url0);
13271 request0.load_flags = 0;
13272 TestCompletionCallback callback0;
13273
13274 int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog());
13275 EXPECT_EQ(ERR_IO_PENDING, rv);
13276 rv = callback0.WaitForResult();
13277 EXPECT_EQ(OK, rv);
13278 }
13279
13280 // Second request to origin.
13281 scoped_ptr<HttpTransaction> trans1(
13282 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13283 HttpRequestInfo request1;
13284 request1.method = "GET";
13285 request1.url = GURL(url1);
13286 request1.load_flags = 0;
13287 TestCompletionCallback callback1;
13288
13289 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
13290 EXPECT_EQ(ERR_IO_PENDING, rv);
rch32320842015-05-16 15:57:0913291 base::MessageLoop::current()->RunUntilIdle();
mmenkee24011922015-12-17 22:12:5913292 if (data.IsPaused())
13293 data.Resume();
bnc1b0e36852015-04-28 15:32:5913294 rv = callback1.WaitForResult();
13295 if (valid) {
13296 EXPECT_EQ(OK, rv);
13297 } else {
13298 if (pooling) {
13299 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
13300 } else {
13301 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv);
13302 }
13303 }
13304 }
13305};
13306
rdsmithebb50aa2015-11-12 03:44:3813307INSTANTIATE_TEST_CASE_P(ProtoPlusDepend,
bnc1b0e36852015-04-28 15:32:5913308 AltSvcCertificateVerificationTest,
rdsmithebb50aa2015-11-12 03:44:3813309 testing::Values(kTestCaseSPDY31,
13310 kTestCaseHTTP2NoPriorityDependencies,
13311 kTestCaseHTTP2PriorityDependencies));
bnc1b0e36852015-04-28 15:32:5913312
13313// The alternative service host must exhibit a certificate that is valid for the
13314// origin host. Test that this is enforced when pooling to an existing
13315// connection.
13316TEST_P(AltSvcCertificateVerificationTest, PoolingValid) {
13317 Run(true, true);
13318}
13319
13320TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) {
13321 Run(true, false);
13322}
13323
13324// The alternative service host must exhibit a certificate that is valid for the
13325// origin host. Test that this is enforced when opening a new connection.
13326TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) {
13327 Run(false, true);
13328}
13329
13330TEST_P(AltSvcCertificateVerificationTest, NewConnectionInvalid) {
13331 Run(false, false);
13332}
13333
bnc5452e2a2015-05-08 16:27:4213334// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
13335// with the alternative server. That connection should not be used.
13336TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
13337 HostPortPair origin("origin.example.org", 443);
13338 HostPortPair alternative("alternative.example.org", 443);
13339
13340 // Negotiate HTTP/1.1 with alternative.example.org.
13341 SSLSocketDataProvider ssl(ASYNC, OK);
13342 ssl.SetNextProto(kProtoHTTP11);
13343 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13344
13345 // No data should be read from the alternative, because HTTP/1.1 is
13346 // negotiated.
13347 StaticSocketDataProvider data;
13348 session_deps_.socket_factory->AddSocketDataProvider(&data);
13349
13350 // This test documents that an alternate Job should not be used if HTTP/1.1 is
13351 // negotiated. In order to test this, a failed connection to the origin is
13352 // mocked. This way the request relies on the alternate Job.
13353 StaticSocketDataProvider data_refused;
13354 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13355 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13356
13357 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3513358 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213359 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc5452e2a2015-05-08 16:27:4213360 base::WeakPtr<HttpServerProperties> http_server_properties =
13361 session->http_server_properties();
13362 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813363 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213364 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc5452e2a2015-05-08 16:27:4213365 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213366 1.0, expiration);
bnc5452e2a2015-05-08 16:27:4213367
13368 scoped_ptr<HttpTransaction> trans(
13369 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13370 HttpRequestInfo request;
13371 request.method = "GET";
13372 request.url = GURL("https://origin.example.org:443");
13373 request.load_flags = 0;
13374 TestCompletionCallback callback;
13375
13376 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
13377 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
13378 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13379 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED, callback.GetResult(rv));
13380}
13381
bnc40448a532015-05-11 19:13:1413382// A request to a server with an alternative service fires two Jobs: one to the
13383// origin, and an alternate one to the alternative server. If the former
13384// succeeds, the request should succeed, even if the latter fails because
13385// HTTP/1.1 is negotiated which is insufficient for alternative service.
13386TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
13387 HostPortPair origin("origin.example.org", 443);
13388 HostPortPair alternative("alternative.example.org", 443);
13389
13390 // Negotiate HTTP/1.1 with alternative.
13391 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
13392 alternative_ssl.SetNextProto(kProtoHTTP11);
13393 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
13394
13395 // No data should be read from the alternative, because HTTP/1.1 is
13396 // negotiated.
13397 StaticSocketDataProvider data;
13398 session_deps_.socket_factory->AddSocketDataProvider(&data);
13399
13400 // Negotiate HTTP/1.1 with origin.
13401 SSLSocketDataProvider origin_ssl(ASYNC, OK);
13402 origin_ssl.SetNextProto(kProtoHTTP11);
13403 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
13404
13405 MockWrite http_writes[] = {
13406 MockWrite(
13407 "GET / HTTP/1.1\r\n"
13408 "Host: origin.example.org\r\n"
13409 "Connection: keep-alive\r\n\r\n"),
13410 MockWrite(
13411 "GET /second HTTP/1.1\r\n"
13412 "Host: origin.example.org\r\n"
13413 "Connection: keep-alive\r\n\r\n"),
13414 };
13415
13416 MockRead http_reads[] = {
13417 MockRead("HTTP/1.1 200 OK\r\n"),
13418 MockRead("Content-Type: text/html\r\n"),
13419 MockRead("Content-Length: 6\r\n\r\n"),
13420 MockRead("foobar"),
13421 MockRead("HTTP/1.1 200 OK\r\n"),
13422 MockRead("Content-Type: text/html\r\n"),
13423 MockRead("Content-Length: 7\r\n\r\n"),
13424 MockRead("another"),
13425 };
13426 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13427 http_writes, arraysize(http_writes));
13428 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13429
13430 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3513431 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213432 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc40448a532015-05-11 19:13:1413433 base::WeakPtr<HttpServerProperties> http_server_properties =
13434 session->http_server_properties();
13435 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813436 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213437 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc40448a532015-05-11 19:13:1413438 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213439 1.0, expiration);
bnc40448a532015-05-11 19:13:1413440
13441 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
13442 HttpRequestInfo request1;
13443 request1.method = "GET";
13444 request1.url = GURL("https://origin.example.org:443");
13445 request1.load_flags = 0;
13446 TestCompletionCallback callback1;
13447
13448 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
13449 rv = callback1.GetResult(rv);
13450 EXPECT_EQ(OK, rv);
13451
13452 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
13453 ASSERT_TRUE(response1 != nullptr);
13454 ASSERT_TRUE(response1->headers.get() != nullptr);
13455 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13456
13457 std::string response_data1;
13458 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data1));
13459 EXPECT_EQ("foobar", response_data1);
13460
13461 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
13462 // for alternative service.
13463 EXPECT_TRUE(
13464 http_server_properties->IsAlternativeServiceBroken(alternative_service));
13465
13466 // Since |alternative_service| is broken, a second transaction to origin
13467 // should not start an alternate Job. It should pool to existing connection
13468 // to origin.
13469 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
13470 HttpRequestInfo request2;
13471 request2.method = "GET";
13472 request2.url = GURL("https://origin.example.org:443/second");
13473 request2.load_flags = 0;
13474 TestCompletionCallback callback2;
13475
13476 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
13477 rv = callback2.GetResult(rv);
13478 EXPECT_EQ(OK, rv);
13479
13480 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
13481 ASSERT_TRUE(response2 != nullptr);
13482 ASSERT_TRUE(response2->headers.get() != nullptr);
13483 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
13484
13485 std::string response_data2;
13486 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data2));
13487 EXPECT_EQ("another", response_data2);
13488}
13489
bnc5452e2a2015-05-08 16:27:4213490// Alternative service requires HTTP/2 (or SPDY), but there is already a
13491// HTTP/1.1 socket open to the alternative server. That socket should not be
13492// used.
13493TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
13494 HostPortPair origin("origin.example.org", 443);
13495 HostPortPair alternative("alternative.example.org", 443);
13496 std::string origin_url = "https://origin.example.org:443";
13497 std::string alternative_url = "https://alternative.example.org:443";
13498
13499 // Negotiate HTTP/1.1 with alternative.example.org.
13500 SSLSocketDataProvider ssl(ASYNC, OK);
13501 ssl.SetNextProto(kProtoHTTP11);
13502 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13503
13504 // HTTP/1.1 data for |request1| and |request2|.
13505 MockWrite http_writes[] = {
13506 MockWrite(
13507 "GET / HTTP/1.1\r\n"
13508 "Host: alternative.example.org\r\n"
13509 "Connection: keep-alive\r\n\r\n"),
13510 MockWrite(
13511 "GET / HTTP/1.1\r\n"
13512 "Host: alternative.example.org\r\n"
13513 "Connection: keep-alive\r\n\r\n"),
13514 };
13515
13516 MockRead http_reads[] = {
13517 MockRead(
13518 "HTTP/1.1 200 OK\r\n"
13519 "Content-Type: text/html; charset=iso-8859-1\r\n"
13520 "Content-Length: 40\r\n\r\n"
13521 "first HTTP/1.1 response from alternative"),
13522 MockRead(
13523 "HTTP/1.1 200 OK\r\n"
13524 "Content-Type: text/html; charset=iso-8859-1\r\n"
13525 "Content-Length: 41\r\n\r\n"
13526 "second HTTP/1.1 response from alternative"),
13527 };
13528 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13529 http_writes, arraysize(http_writes));
13530 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13531
13532 // This test documents that an alternate Job should not pool to an already
13533 // existing HTTP/1.1 connection. In order to test this, a failed connection
13534 // to the origin is mocked. This way |request2| relies on the alternate Job.
13535 StaticSocketDataProvider data_refused;
13536 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13537 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13538
13539 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3513540 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213541 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc5452e2a2015-05-08 16:27:4213542 base::WeakPtr<HttpServerProperties> http_server_properties =
13543 session->http_server_properties();
13544 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813545 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213546 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc5452e2a2015-05-08 16:27:4213547 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213548 1.0, expiration);
bnc5452e2a2015-05-08 16:27:4213549
13550 // First transaction to alternative to open an HTTP/1.1 socket.
13551 scoped_ptr<HttpTransaction> trans1(
13552 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13553 HttpRequestInfo request1;
13554 request1.method = "GET";
13555 request1.url = GURL(alternative_url);
13556 request1.load_flags = 0;
13557 TestCompletionCallback callback1;
13558
13559 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
13560 EXPECT_EQ(OK, callback1.GetResult(rv));
13561 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
13562 ASSERT_TRUE(response1);
13563 ASSERT_TRUE(response1->headers.get());
13564 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13565 EXPECT_TRUE(response1->was_npn_negotiated);
13566 EXPECT_FALSE(response1->was_fetched_via_spdy);
13567 std::string response_data1;
13568 ASSERT_EQ(OK, ReadTransaction(trans1.get(), &response_data1));
13569 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
13570
13571 // Request for origin.example.org, which has an alternative service. This
13572 // will start two Jobs: the alternative looks for connections to pool to,
13573 // finds one which is HTTP/1.1, and should ignore it, and should not try to
13574 // open other connections to alternative server. The Job to origin fails, so
13575 // this request fails.
13576 scoped_ptr<HttpTransaction> trans2(
13577 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13578 HttpRequestInfo request2;
13579 request2.method = "GET";
13580 request2.url = GURL(origin_url);
13581 request2.load_flags = 0;
13582 TestCompletionCallback callback2;
13583
13584 rv = trans2->Start(&request2, callback2.callback(), BoundNetLog());
13585 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback2.GetResult(rv));
13586
13587 // Another transaction to alternative. This is to test that the HTTP/1.1
13588 // socket is still open and in the pool.
13589 scoped_ptr<HttpTransaction> trans3(
13590 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13591 HttpRequestInfo request3;
13592 request3.method = "GET";
13593 request3.url = GURL(alternative_url);
13594 request3.load_flags = 0;
13595 TestCompletionCallback callback3;
13596
13597 rv = trans3->Start(&request3, callback3.callback(), BoundNetLog());
13598 EXPECT_EQ(OK, callback3.GetResult(rv));
13599 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
13600 ASSERT_TRUE(response3);
13601 ASSERT_TRUE(response3->headers.get());
13602 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
13603 EXPECT_TRUE(response3->was_npn_negotiated);
13604 EXPECT_FALSE(response3->was_fetched_via_spdy);
13605 std::string response_data3;
13606 ASSERT_EQ(OK, ReadTransaction(trans3.get(), &response_data3));
13607 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
13608}
13609
[email protected]23e482282013-06-14 16:08:0213610TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2313611 const std::string https_url = "https://www.example.org:8080/";
13612 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0413613
rdsmithebb50aa2015-11-12 03:44:3813614 // Separate SPDY util instance for naked and wrapped requests.
13615 SpdyTestUtil spdy_util_wrapped(GetProtocol(), GetDependenciesFromPriority());
13616
[email protected]8450d722012-07-02 19:14:0413617 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2313618 const HostPortPair host_port_pair("www.example.org", 8080);
lgarrona91df87f2014-12-05 00:51:3413619 scoped_ptr<SpdyFrame> connect(
13620 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
[email protected]cdf8f7e72013-05-23 10:56:4613621 scoped_ptr<SpdyFrame> req1(
rdsmithebb50aa2015-11-12 03:44:3813622 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
[email protected]23e482282013-06-14 16:08:0213623 scoped_ptr<SpdyFrame> wrapped_req1(
13624 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3913625
13626 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
[email protected]745aa9c2014-06-27 02:21:2913627 SpdyHeaderBlock req2_block;
bnc7ecc1122015-09-28 13:22:4913628 spdy_util_.MaybeAddVersionHeader(&req2_block);
[email protected]745aa9c2014-06-27 02:21:2913629 req2_block[spdy_util_.GetMethodKey()] = "GET";
bncce36dca22015-04-21 22:11:2313630 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
[email protected]745aa9c2014-06-27 02:21:2913631 req2_block[spdy_util_.GetSchemeKey()] = "http";
bnc7ecc1122015-09-28 13:22:4913632 req2_block[spdy_util_.GetPathKey()] = "/";
[email protected]601e03f12014-04-06 16:26:3913633 scoped_ptr<SpdyFrame> req2(
[email protected]745aa9c2014-06-27 02:21:2913634 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
[email protected]8450d722012-07-02 19:14:0413635
13636 MockWrite writes1[] = {
mmenke666a6fea2015-12-19 04:16:3313637 CreateMockWrite(*connect, 0), CreateMockWrite(*wrapped_req1, 2),
13638 CreateMockWrite(*req2, 6),
[email protected]8450d722012-07-02 19:14:0413639 };
13640
[email protected]23e482282013-06-14 16:08:0213641 scoped_ptr<SpdyFrame> conn_resp(
13642 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13643 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13644 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
13645 scoped_ptr<SpdyFrame> wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3813646 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
[email protected]23e482282013-06-14 16:08:0213647 scoped_ptr<SpdyFrame> wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3813648 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
[email protected]23e482282013-06-14 16:08:0213649 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13650 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3313651 MockRead reads1[] = {
13652 CreateMockRead(*conn_resp, 1),
13653 MockRead(ASYNC, ERR_IO_PENDING, 3),
13654 CreateMockRead(*wrapped_resp1, 4),
13655 CreateMockRead(*wrapped_body1, 5),
13656 MockRead(ASYNC, ERR_IO_PENDING, 7),
13657 CreateMockRead(*resp2, 8),
13658 CreateMockRead(*body2, 9),
13659 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
13660 };
[email protected]8450d722012-07-02 19:14:0413661
mmenke666a6fea2015-12-19 04:16:3313662 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
13663 arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0413664 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5713665 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0413666
rdsmith82957ad2015-09-16 19:42:0313667 session_deps_.proxy_service =
13668 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:5113669 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0713670 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0413671 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
rdsmithebb50aa2015-11-12 03:44:3813672 ssl1.SetNextProto(GetProtocol());
mmenke666a6fea2015-12-19 04:16:3313673 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0413674 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
rdsmithebb50aa2015-11-12 03:44:3813675 ssl2.SetNextProto(GetProtocol());
mmenke666a6fea2015-12-19 04:16:3313676 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13677 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0413678
mmenke666a6fea2015-12-19 04:16:3313679 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0413680
13681 // Start the first transaction to set up the SpdySession
13682 HttpRequestInfo request1;
13683 request1.method = "GET";
13684 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0413685 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013686 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0413687 TestCompletionCallback callback1;
mmenke666a6fea2015-12-19 04:16:3313688 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
[email protected]8450d722012-07-02 19:14:0413689
mmenke666a6fea2015-12-19 04:16:3313690 // This pause is a hack to avoid running into https://crbug.com/497228.
13691 data1.RunUntilPaused();
13692 base::RunLoop().RunUntilIdle();
13693 data1.Resume();
13694 EXPECT_EQ(OK, callback1.GetResult(rv));
[email protected]8450d722012-07-02 19:14:0413695 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13696
[email protected]f6c63db52013-02-02 00:35:2213697 LoadTimingInfo load_timing_info1;
13698 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
13699 TestLoadTimingNotReusedWithPac(load_timing_info1,
13700 CONNECT_TIMING_HAS_SSL_TIMES);
13701
mmenke666a6fea2015-12-19 04:16:3313702 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0413703 HttpRequestInfo request2;
13704 request2.method = "GET";
13705 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0413706 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013707 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0413708 TestCompletionCallback callback2;
mmenke666a6fea2015-12-19 04:16:3313709 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
[email protected]8450d722012-07-02 19:14:0413710
mmenke666a6fea2015-12-19 04:16:3313711 // This pause is a hack to avoid running into https://crbug.com/497228.
13712 data1.RunUntilPaused();
13713 base::RunLoop().RunUntilIdle();
13714 data1.Resume();
13715 EXPECT_EQ(OK, callback2.GetResult(rv));
13716
[email protected]8450d722012-07-02 19:14:0413717 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2213718
13719 LoadTimingInfo load_timing_info2;
13720 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
13721 // The established SPDY sessions is considered reused by the HTTP request.
13722 TestLoadTimingReusedWithPac(load_timing_info2);
13723 // HTTP requests over a SPDY session should have a different connection
13724 // socket_log_id than requests over a tunnel.
13725 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0413726}
13727
[email protected]2d88e7d2012-07-19 17:55:1713728// Test that in the case where we have a SPDY session to a SPDY proxy
13729// that we do not pool other origins that resolve to the same IP when
13730// the certificate does not match the new origin.
13731// http://crbug.com/134690
[email protected]23e482282013-06-14 16:08:0213732TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2313733 const std::string url1 = "http://www.example.org/";
13734 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1713735 const std::string ip_addr = "1.2.3.4";
13736
rdsmithebb50aa2015-11-12 03:44:3813737 // Second SpdyTestUtil instance for the second socket.
13738 SpdyTestUtil spdy_util_secure(GetProtocol(), GetDependenciesFromPriority());
13739
[email protected]2d88e7d2012-07-19 17:55:1713740 // SPDY GET for HTTP URL (through SPDY proxy)
[email protected]23e482282013-06-14 16:08:0213741 scoped_ptr<SpdyHeaderBlock> headers(
bncce36dca22015-04-21 22:11:2313742 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
[email protected]745aa9c2014-06-27 02:21:2913743 scoped_ptr<SpdyFrame> req1(
13744 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]2d88e7d2012-07-19 17:55:1713745
13746 MockWrite writes1[] = {
13747 CreateMockWrite(*req1, 0),
13748 };
13749
[email protected]23e482282013-06-14 16:08:0213750 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13751 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1713752 MockRead reads1[] = {
mmenke666a6fea2015-12-19 04:16:3313753 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(*resp1, 2),
13754 CreateMockRead(*body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1713755 };
13756
mmenke666a6fea2015-12-19 04:16:3313757 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
13758 arraysize(writes1));
[email protected]2d88e7d2012-07-19 17:55:1713759 IPAddressNumber ip;
13760 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
13761 IPEndPoint peer_addr = IPEndPoint(ip, 443);
13762 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3313763 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1713764
13765 // SPDY GET for HTTPS URL (direct)
[email protected]cdf8f7e72013-05-23 10:56:4613766 scoped_ptr<SpdyFrame> req2(
rdsmithebb50aa2015-11-12 03:44:3813767 spdy_util_secure.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1713768
13769 MockWrite writes2[] = {
13770 CreateMockWrite(*req2, 0),
13771 };
13772
rdsmithebb50aa2015-11-12 03:44:3813773 scoped_ptr<SpdyFrame> resp2(
13774 spdy_util_secure.ConstructSpdyGetSynReply(NULL, 0, 1));
13775 scoped_ptr<SpdyFrame> body2(spdy_util_secure.ConstructSpdyBodyFrame(1, true));
mmenke666a6fea2015-12-19 04:16:3313776 MockRead reads2[] = {CreateMockRead(*resp2, 1), CreateMockRead(*body2, 2),
13777 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1713778
mmenke666a6fea2015-12-19 04:16:3313779 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13780 arraysize(writes2));
[email protected]2d88e7d2012-07-19 17:55:1713781 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3313782 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1713783
13784 // Set up a proxy config that sends HTTP requests to a proxy, and
13785 // all others direct.
13786 ProxyConfig proxy_config;
13787 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
[email protected]bb88e1d32013-05-03 23:11:0713788 session_deps_.proxy_service.reset(new ProxyService(
csharrisonb7e3a082015-09-22 19:13:0413789 make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)), nullptr,
13790 NULL));
[email protected]2d88e7d2012-07-19 17:55:1713791
bncce36dca22015-04-21 22:11:2313792 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
rdsmithebb50aa2015-11-12 03:44:3813793 ssl1.SetNextProto(GetProtocol());
[email protected]2d88e7d2012-07-19 17:55:1713794 // Load a valid cert. Note, that this does not need to
13795 // be valid for proxy because the MockSSLClientSocket does
13796 // not actually verify it. But SpdySession will use this
13797 // to see if it is valid for the new origin
bncce36dca22015-04-21 22:11:2313798 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
13799 ASSERT_TRUE(ssl1.cert.get());
mmenke666a6fea2015-12-19 04:16:3313800 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13801 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1713802
13803 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
rdsmithebb50aa2015-11-12 03:44:3813804 ssl2.SetNextProto(GetProtocol());
mmenke666a6fea2015-12-19 04:16:3313805 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13806 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1713807
[email protected]bb88e1d32013-05-03 23:11:0713808 session_deps_.host_resolver.reset(new MockCachingHostResolver());
bncce36dca22015-04-21 22:11:2313809 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0713810 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1713811
mmenke666a6fea2015-12-19 04:16:3313812 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1713813
13814 // Start the first transaction to set up the SpdySession
13815 HttpRequestInfo request1;
13816 request1.method = "GET";
13817 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1713818 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013819 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713820 TestCompletionCallback callback1;
13821 ASSERT_EQ(ERR_IO_PENDING,
13822 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
mmenke666a6fea2015-12-19 04:16:3313823 // This pause is a hack to avoid running into https://crbug.com/497228.
13824 data1.RunUntilPaused();
13825 base::RunLoop().RunUntilIdle();
13826 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1713827
[email protected]2d88e7d2012-07-19 17:55:1713828 EXPECT_EQ(OK, callback1.WaitForResult());
13829 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13830
13831 // Now, start the HTTP request
13832 HttpRequestInfo request2;
13833 request2.method = "GET";
13834 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1713835 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013836 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713837 TestCompletionCallback callback2;
13838 EXPECT_EQ(ERR_IO_PENDING,
13839 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413840 base::MessageLoop::current()->RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1713841
13842 ASSERT_TRUE(callback2.have_result());
13843 EXPECT_EQ(OK, callback2.WaitForResult());
13844 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13845}
13846
[email protected]85f97342013-04-17 06:12:2413847// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
13848// error) in SPDY session, removes the socket from pool and closes the SPDY
13849// session. Verify that new url's from the same HttpNetworkSession (and a new
13850// SpdySession) do work. http://crbug.com/224701
[email protected]23e482282013-06-14 16:08:0213851TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2313852 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2413853
13854 MockRead reads1[] = {
13855 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
13856 };
13857
mmenke11eb5152015-06-09 14:50:5013858 SequencedSocketData data1(reads1, arraysize(reads1), NULL, 0);
[email protected]85f97342013-04-17 06:12:2413859
[email protected]cdf8f7e72013-05-23 10:56:4613860 scoped_ptr<SpdyFrame> req2(
13861 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2413862 MockWrite writes2[] = {
13863 CreateMockWrite(*req2, 0),
13864 };
13865
[email protected]23e482282013-06-14 16:08:0213866 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13867 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]85f97342013-04-17 06:12:2413868 MockRead reads2[] = {
13869 CreateMockRead(*resp2, 1),
13870 CreateMockRead(*body2, 2),
13871 MockRead(ASYNC, OK, 3) // EOF
13872 };
13873
mmenke11eb5152015-06-09 14:50:5013874 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13875 arraysize(writes2));
[email protected]85f97342013-04-17 06:12:2413876
[email protected]85f97342013-04-17 06:12:2413877 SSLSocketDataProvider ssl1(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813878 ssl1.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:5013879 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13880 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2413881
13882 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813883 ssl2.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:5013884 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13885 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2413886
mmenkee65e7af2015-10-13 17:16:4213887 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5013888 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2413889
13890 // Start the first transaction to set up the SpdySession and verify that
13891 // connection was closed.
13892 HttpRequestInfo request1;
13893 request1.method = "GET";
13894 request1.url = GURL(https_url);
13895 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013896 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2413897 TestCompletionCallback callback1;
13898 EXPECT_EQ(ERR_IO_PENDING,
13899 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]85f97342013-04-17 06:12:2413900 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
13901
13902 // Now, start the second request and make sure it succeeds.
13903 HttpRequestInfo request2;
13904 request2.method = "GET";
13905 request2.url = GURL(https_url);
13906 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013907 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2413908 TestCompletionCallback callback2;
13909 EXPECT_EQ(ERR_IO_PENDING,
13910 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]85f97342013-04-17 06:12:2413911
mmenke11eb5152015-06-09 14:50:5013912 ASSERT_EQ(OK, callback2.WaitForResult());
[email protected]85f97342013-04-17 06:12:2413913 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13914}
13915
[email protected]23e482282013-06-14 16:08:0213916TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]d7599122014-05-24 03:37:2313917 session_deps_.next_protos = SpdyNextProtos();
[email protected]483fa202013-05-14 01:07:0313918 ClientSocketPoolManager::set_max_sockets_per_group(
13919 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13920 ClientSocketPoolManager::set_max_sockets_per_pool(
13921 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13922
13923 // Use two different hosts with different IPs so they don't get pooled.
13924 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
13925 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
mmenkee65e7af2015-10-13 17:16:4213926 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0313927
13928 SSLSocketDataProvider ssl1(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813929 ssl1.SetNextProto(GetProtocol());
[email protected]483fa202013-05-14 01:07:0313930 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813931 ssl2.SetNextProto(GetProtocol());
[email protected]483fa202013-05-14 01:07:0313932 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13933 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13934
[email protected]cdf8f7e72013-05-23 10:56:4613935 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
[email protected]483fa202013-05-14 01:07:0313936 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
13937 MockWrite spdy1_writes[] = {
rch8e6c6c42015-05-01 14:05:1313938 CreateMockWrite(*host1_req, 0),
[email protected]483fa202013-05-14 01:07:0313939 };
[email protected]23e482282013-06-14 16:08:0213940 scoped_ptr<SpdyFrame> host1_resp(
13941 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13942 scoped_ptr<SpdyFrame> host1_resp_body(
13943 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]483fa202013-05-14 01:07:0313944 MockRead spdy1_reads[] = {
mmenkee24011922015-12-17 22:12:5913945 CreateMockRead(*host1_resp, 1), CreateMockRead(*host1_resp_body, 2),
13946 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0313947 };
13948
rdsmithebb50aa2015-11-12 03:44:3813949 // Use a separate test instance for the separate SpdySession that will be
13950 // created.
13951 SpdyTestUtil spdy_util_2(GetProtocol(), GetDependenciesFromPriority());
rch8e6c6c42015-05-01 14:05:1313952 scoped_ptr<SequencedSocketData> spdy1_data(
13953 new SequencedSocketData(spdy1_reads, arraysize(spdy1_reads), spdy1_writes,
13954 arraysize(spdy1_writes)));
[email protected]483fa202013-05-14 01:07:0313955 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
13956
rdsmithebb50aa2015-11-12 03:44:3813957 scoped_ptr<SpdyFrame> host2_req(spdy_util_2.ConstructSpdyGet(
[email protected]483fa202013-05-14 01:07:0313958 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
13959 MockWrite spdy2_writes[] = {
rch8e6c6c42015-05-01 14:05:1313960 CreateMockWrite(*host2_req, 0),
[email protected]483fa202013-05-14 01:07:0313961 };
[email protected]23e482282013-06-14 16:08:0213962 scoped_ptr<SpdyFrame> host2_resp(
rdsmithebb50aa2015-11-12 03:44:3813963 spdy_util_2.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]23e482282013-06-14 16:08:0213964 scoped_ptr<SpdyFrame> host2_resp_body(
rdsmithebb50aa2015-11-12 03:44:3813965 spdy_util_2.ConstructSpdyBodyFrame(1, true));
[email protected]483fa202013-05-14 01:07:0313966 MockRead spdy2_reads[] = {
mmenkee24011922015-12-17 22:12:5913967 CreateMockRead(*host2_resp, 1), CreateMockRead(*host2_resp_body, 2),
13968 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0313969 };
13970
rch8e6c6c42015-05-01 14:05:1313971 scoped_ptr<SequencedSocketData> spdy2_data(
13972 new SequencedSocketData(spdy2_reads, arraysize(spdy2_reads), spdy2_writes,
13973 arraysize(spdy2_writes)));
[email protected]483fa202013-05-14 01:07:0313974 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
13975
13976 MockWrite http_write[] = {
13977 MockWrite("GET / HTTP/1.1\r\n"
13978 "Host: www.a.com\r\n"
13979 "Connection: keep-alive\r\n\r\n"),
13980 };
13981
13982 MockRead http_read[] = {
13983 MockRead("HTTP/1.1 200 OK\r\n"),
13984 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
13985 MockRead("Content-Length: 6\r\n\r\n"),
13986 MockRead("hello!"),
13987 };
13988 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
13989 http_write, arraysize(http_write));
13990 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13991
13992 HostPortPair host_port_pair_a("www.a.com", 443);
[email protected]e6d017652013-05-17 18:01:4013993 SpdySessionKey spdy_session_key_a(
[email protected]314b03992014-04-01 01:28:5313994 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0313995 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613996 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313997
13998 TestCompletionCallback callback;
13999 HttpRequestInfo request1;
14000 request1.method = "GET";
14001 request1.url = GURL("https://www.a.com/");
14002 request1.load_flags = 0;
14003 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5014004 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0314005
14006 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
14007 EXPECT_EQ(ERR_IO_PENDING, rv);
14008 EXPECT_EQ(OK, callback.WaitForResult());
14009
14010 const HttpResponseInfo* response = trans->GetResponseInfo();
14011 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5014012 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0214013 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0314014 EXPECT_TRUE(response->was_fetched_via_spdy);
14015 EXPECT_TRUE(response->was_npn_negotiated);
14016
14017 std::string response_data;
14018 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
14019 EXPECT_EQ("hello!", response_data);
14020 trans.reset();
14021 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2614022 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314023
14024 HostPortPair host_port_pair_b("www.b.com", 443);
[email protected]e6d017652013-05-17 18:01:4014025 SpdySessionKey spdy_session_key_b(
[email protected]314b03992014-04-01 01:28:5314026 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0314027 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614028 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0314029 HttpRequestInfo request2;
14030 request2.method = "GET";
14031 request2.url = GURL("https://www.b.com/");
14032 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5014033 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0314034
14035 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
14036 EXPECT_EQ(ERR_IO_PENDING, rv);
14037 EXPECT_EQ(OK, callback.WaitForResult());
14038
14039 response = trans->GetResponseInfo();
14040 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5014041 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0214042 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0314043 EXPECT_TRUE(response->was_fetched_via_spdy);
14044 EXPECT_TRUE(response->was_npn_negotiated);
14045 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
14046 EXPECT_EQ("hello!", response_data);
14047 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614048 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314049 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2614050 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0314051
14052 HostPortPair host_port_pair_a1("www.a.com", 80);
[email protected]e6d017652013-05-17 18:01:4014053 SpdySessionKey spdy_session_key_a1(
[email protected]314b03992014-04-01 01:28:5314054 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0314055 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614056 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0314057 HttpRequestInfo request3;
14058 request3.method = "GET";
14059 request3.url = GURL("http://www.a.com/");
14060 request3.load_flags = 0;
[email protected]90499482013-06-01 00:39:5014061 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0314062
14063 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
14064 EXPECT_EQ(ERR_IO_PENDING, rv);
14065 EXPECT_EQ(OK, callback.WaitForResult());
14066
14067 response = trans->GetResponseInfo();
14068 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5014069 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]483fa202013-05-14 01:07:0314070 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14071 EXPECT_FALSE(response->was_fetched_via_spdy);
14072 EXPECT_FALSE(response->was_npn_negotiated);
14073 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
14074 EXPECT_EQ("hello!", response_data);
14075 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614076 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314077 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614078 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0314079}
14080
[email protected]79e1fd62013-06-20 06:50:0414081TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
14082 HttpRequestInfo request;
14083 request.method = "GET";
bncce36dca22015-04-21 22:11:2314084 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414085 request.load_flags = 0;
14086
mmenkee65e7af2015-10-13 17:16:4214087 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414088 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114089 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414090
ttuttled9dbc652015-09-29 20:00:5914091 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0414092 StaticSocketDataProvider data;
14093 data.set_connect_data(mock_connect);
14094 session_deps_.socket_factory->AddSocketDataProvider(&data);
14095
14096 TestCompletionCallback callback;
14097
14098 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14099 EXPECT_EQ(ERR_IO_PENDING, rv);
14100
14101 rv = callback.WaitForResult();
ttuttled9dbc652015-09-29 20:00:5914102 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
[email protected]79e1fd62013-06-20 06:50:0414103
[email protected]79e1fd62013-06-20 06:50:0414104 // We don't care whether this succeeds or fails, but it shouldn't crash.
14105 HttpRequestHeaders request_headers;
14106 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4714107
14108 ConnectionAttempts attempts;
14109 trans->GetConnectionAttempts(&attempts);
14110 ASSERT_EQ(1u, attempts.size());
ttuttled9dbc652015-09-29 20:00:5914111 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
14112
14113 IPEndPoint endpoint;
14114 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
14115 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0414116}
14117
14118TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
14119 HttpRequestInfo request;
14120 request.method = "GET";
bncce36dca22015-04-21 22:11:2314121 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414122 request.load_flags = 0;
14123
mmenkee65e7af2015-10-13 17:16:4214124 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414125 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114126 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414127
ttuttled9dbc652015-09-29 20:00:5914128 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0414129 StaticSocketDataProvider data;
14130 data.set_connect_data(mock_connect);
14131 session_deps_.socket_factory->AddSocketDataProvider(&data);
14132
14133 TestCompletionCallback callback;
14134
14135 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14136 EXPECT_EQ(ERR_IO_PENDING, rv);
14137
14138 rv = callback.WaitForResult();
ttuttled9dbc652015-09-29 20:00:5914139 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
[email protected]79e1fd62013-06-20 06:50:0414140
[email protected]79e1fd62013-06-20 06:50:0414141 // We don't care whether this succeeds or fails, but it shouldn't crash.
14142 HttpRequestHeaders request_headers;
14143 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4714144
14145 ConnectionAttempts attempts;
14146 trans->GetConnectionAttempts(&attempts);
14147 ASSERT_EQ(1u, attempts.size());
ttuttled9dbc652015-09-29 20:00:5914148 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
14149
14150 IPEndPoint endpoint;
14151 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
14152 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0414153}
14154
14155TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
14156 HttpRequestInfo request;
14157 request.method = "GET";
bncce36dca22015-04-21 22:11:2314158 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414159 request.load_flags = 0;
14160
mmenkee65e7af2015-10-13 17:16:4214161 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414162 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114163 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414164
14165 MockWrite data_writes[] = {
14166 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14167 };
14168 MockRead data_reads[] = {
14169 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
14170 };
14171
14172 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14173 data_writes, arraysize(data_writes));
14174 session_deps_.socket_factory->AddSocketDataProvider(&data);
14175
14176 TestCompletionCallback callback;
14177
14178 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14179 EXPECT_EQ(ERR_IO_PENDING, rv);
14180
14181 rv = callback.WaitForResult();
14182 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14183
[email protected]79e1fd62013-06-20 06:50:0414184 HttpRequestHeaders request_headers;
14185 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14186 EXPECT_TRUE(request_headers.HasHeader("Host"));
14187}
14188
14189TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
14190 HttpRequestInfo request;
14191 request.method = "GET";
bncce36dca22015-04-21 22:11:2314192 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414193 request.load_flags = 0;
14194
mmenkee65e7af2015-10-13 17:16:4214195 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414196 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114197 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414198
14199 MockWrite data_writes[] = {
14200 MockWrite(ASYNC, ERR_CONNECTION_RESET),
14201 };
14202 MockRead data_reads[] = {
14203 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
14204 };
14205
14206 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14207 data_writes, arraysize(data_writes));
14208 session_deps_.socket_factory->AddSocketDataProvider(&data);
14209
14210 TestCompletionCallback callback;
14211
14212 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14213 EXPECT_EQ(ERR_IO_PENDING, rv);
14214
14215 rv = callback.WaitForResult();
14216 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14217
[email protected]79e1fd62013-06-20 06:50:0414218 HttpRequestHeaders request_headers;
14219 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14220 EXPECT_TRUE(request_headers.HasHeader("Host"));
14221}
14222
14223TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
14224 HttpRequestInfo request;
14225 request.method = "GET";
bncce36dca22015-04-21 22:11:2314226 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414227 request.load_flags = 0;
14228
mmenkee65e7af2015-10-13 17:16:4214229 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414230 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114231 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414232
14233 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314234 MockWrite(
14235 "GET / HTTP/1.1\r\n"
14236 "Host: www.example.org\r\n"
14237 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414238 };
14239 MockRead data_reads[] = {
14240 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
14241 };
14242
14243 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14244 data_writes, arraysize(data_writes));
14245 session_deps_.socket_factory->AddSocketDataProvider(&data);
14246
14247 TestCompletionCallback callback;
14248
14249 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14250 EXPECT_EQ(ERR_IO_PENDING, rv);
14251
14252 rv = callback.WaitForResult();
14253 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14254
[email protected]79e1fd62013-06-20 06:50:0414255 HttpRequestHeaders request_headers;
14256 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14257 EXPECT_TRUE(request_headers.HasHeader("Host"));
14258}
14259
14260TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
14261 HttpRequestInfo request;
14262 request.method = "GET";
bncce36dca22015-04-21 22:11:2314263 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414264 request.load_flags = 0;
14265
mmenkee65e7af2015-10-13 17:16:4214266 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414267 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114268 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414269
14270 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314271 MockWrite(
14272 "GET / HTTP/1.1\r\n"
14273 "Host: www.example.org\r\n"
14274 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414275 };
14276 MockRead data_reads[] = {
14277 MockRead(ASYNC, ERR_CONNECTION_RESET),
14278 };
14279
14280 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14281 data_writes, arraysize(data_writes));
14282 session_deps_.socket_factory->AddSocketDataProvider(&data);
14283
14284 TestCompletionCallback callback;
14285
14286 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14287 EXPECT_EQ(ERR_IO_PENDING, rv);
14288
14289 rv = callback.WaitForResult();
14290 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14291
[email protected]79e1fd62013-06-20 06:50:0414292 HttpRequestHeaders request_headers;
14293 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14294 EXPECT_TRUE(request_headers.HasHeader("Host"));
14295}
14296
14297TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
14298 HttpRequestInfo request;
14299 request.method = "GET";
bncce36dca22015-04-21 22:11:2314300 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414301 request.load_flags = 0;
14302 request.extra_headers.SetHeader("X-Foo", "bar");
14303
mmenkee65e7af2015-10-13 17:16:4214304 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414305 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114306 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414307
14308 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314309 MockWrite(
14310 "GET / HTTP/1.1\r\n"
14311 "Host: www.example.org\r\n"
14312 "Connection: keep-alive\r\n"
14313 "X-Foo: bar\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414314 };
14315 MockRead data_reads[] = {
14316 MockRead("HTTP/1.1 200 OK\r\n"
14317 "Content-Length: 5\r\n\r\n"
14318 "hello"),
14319 MockRead(ASYNC, ERR_UNEXPECTED),
14320 };
14321
14322 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14323 data_writes, arraysize(data_writes));
14324 session_deps_.socket_factory->AddSocketDataProvider(&data);
14325
14326 TestCompletionCallback callback;
14327
14328 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14329 EXPECT_EQ(ERR_IO_PENDING, rv);
14330
14331 rv = callback.WaitForResult();
14332 EXPECT_EQ(OK, rv);
14333
14334 HttpRequestHeaders request_headers;
14335 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14336 std::string foo;
14337 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
14338 EXPECT_EQ("bar", foo);
14339}
14340
[email protected]bf828982013-08-14 18:01:4714341namespace {
14342
yhiranoa7e05bb2014-11-06 05:40:3914343// Fake HttpStream that simply records calls to SetPriority().
14344class FakeStream : public HttpStream,
[email protected]e86839fd2013-08-14 18:29:0314345 public base::SupportsWeakPtr<FakeStream> {
14346 public:
14347 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
dchengb03027d2014-10-21 12:00:2014348 ~FakeStream() override {}
[email protected]e86839fd2013-08-14 18:29:0314349
14350 RequestPriority priority() const { return priority_; }
14351
dchengb03027d2014-10-21 12:00:2014352 int InitializeStream(const HttpRequestInfo* request_info,
14353 RequestPriority priority,
14354 const BoundNetLog& net_log,
14355 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314356 return ERR_IO_PENDING;
14357 }
14358
dchengb03027d2014-10-21 12:00:2014359 int SendRequest(const HttpRequestHeaders& request_headers,
14360 HttpResponseInfo* response,
14361 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314362 ADD_FAILURE();
14363 return ERR_UNEXPECTED;
14364 }
14365
dchengb03027d2014-10-21 12:00:2014366 int ReadResponseHeaders(const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314367 ADD_FAILURE();
14368 return ERR_UNEXPECTED;
14369 }
14370
dchengb03027d2014-10-21 12:00:2014371 int ReadResponseBody(IOBuffer* buf,
14372 int buf_len,
14373 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314374 ADD_FAILURE();
14375 return ERR_UNEXPECTED;
14376 }
14377
dchengb03027d2014-10-21 12:00:2014378 void Close(bool not_reusable) override {}
[email protected]e86839fd2013-08-14 18:29:0314379
dchengb03027d2014-10-21 12:00:2014380 bool IsResponseBodyComplete() const override {
[email protected]e86839fd2013-08-14 18:29:0314381 ADD_FAILURE();
14382 return false;
14383 }
14384
dchengb03027d2014-10-21 12:00:2014385 bool IsConnectionReused() const override {
[email protected]e86839fd2013-08-14 18:29:0314386 ADD_FAILURE();
14387 return false;
14388 }
14389
dchengb03027d2014-10-21 12:00:2014390 void SetConnectionReused() override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0314391
mmenkebd84c392015-09-02 14:12:3414392 bool CanReuseConnection() const override { return false; }
[email protected]e86839fd2013-08-14 18:29:0314393
sclittle4de1bab92015-09-22 21:28:2414394 int64_t GetTotalReceivedBytes() const override {
[email protected]bc92bc972013-12-13 08:32:5914395 ADD_FAILURE();
14396 return 0;
14397 }
14398
sclittlebe1ccf62015-09-02 19:40:3614399 int64_t GetTotalSentBytes() const override {
14400 ADD_FAILURE();
14401 return 0;
14402 }
14403
dchengb03027d2014-10-21 12:00:2014404 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
[email protected]e86839fd2013-08-14 18:29:0314405 ADD_FAILURE();
14406 return false;
14407 }
14408
dchengb03027d2014-10-21 12:00:2014409 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
14410
14411 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
[email protected]e86839fd2013-08-14 18:29:0314412 ADD_FAILURE();
14413 }
14414
ttuttled9dbc652015-09-29 20:00:5914415 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
14416
nharperb7441ef2016-01-25 23:54:1414417 Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
14418 std::vector<uint8_t>* out) override {
14419 ADD_FAILURE();
14420 return ERR_NOT_IMPLEMENTED;
14421 }
14422
dchengb03027d2014-10-21 12:00:2014423 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0314424
zhongyica364fbb2015-12-12 03:39:1214425 void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
14426
dchengb03027d2014-10-21 12:00:2014427 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]e86839fd2013-08-14 18:29:0314428
yhiranoa7e05bb2014-11-06 05:40:3914429 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
14430
14431 HttpStream* RenewStreamForAuth() override { return NULL; }
14432
[email protected]e86839fd2013-08-14 18:29:0314433 private:
14434 RequestPriority priority_;
14435
14436 DISALLOW_COPY_AND_ASSIGN(FakeStream);
14437};
14438
14439// Fake HttpStreamRequest that simply records calls to SetPriority()
14440// and vends FakeStreams with its current priority.
[email protected]bf828982013-08-14 18:01:4714441class FakeStreamRequest : public HttpStreamRequest,
14442 public base::SupportsWeakPtr<FakeStreamRequest> {
14443 public:
[email protected]e86839fd2013-08-14 18:29:0314444 FakeStreamRequest(RequestPriority priority,
14445 HttpStreamRequest::Delegate* delegate)
14446 : priority_(priority),
[email protected]831e4a32013-11-14 02:14:4414447 delegate_(delegate),
14448 websocket_stream_create_helper_(NULL) {}
14449
14450 FakeStreamRequest(RequestPriority priority,
14451 HttpStreamRequest::Delegate* delegate,
14452 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
14453 : priority_(priority),
14454 delegate_(delegate),
14455 websocket_stream_create_helper_(create_helper) {}
[email protected]e86839fd2013-08-14 18:29:0314456
dchengb03027d2014-10-21 12:00:2014457 ~FakeStreamRequest() override {}
[email protected]bf828982013-08-14 18:01:4714458
14459 RequestPriority priority() const { return priority_; }
14460
[email protected]831e4a32013-11-14 02:14:4414461 const WebSocketHandshakeStreamBase::CreateHelper*
14462 websocket_stream_create_helper() const {
14463 return websocket_stream_create_helper_;
14464 }
14465
[email protected]e86839fd2013-08-14 18:29:0314466 // Create a new FakeStream and pass it to the request's
14467 // delegate. Returns a weak pointer to the FakeStream.
14468 base::WeakPtr<FakeStream> FinishStreamRequest() {
14469 FakeStream* fake_stream = new FakeStream(priority_);
14470 // Do this before calling OnStreamReady() as OnStreamReady() may
14471 // immediately delete |fake_stream|.
14472 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
14473 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
14474 return weak_stream;
14475 }
14476
dchengb03027d2014-10-21 12:00:2014477 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
[email protected]bf828982013-08-14 18:01:4714478 ADD_FAILURE();
14479 return ERR_UNEXPECTED;
14480 }
14481
dchengb03027d2014-10-21 12:00:2014482 LoadState GetLoadState() const override {
[email protected]bf828982013-08-14 18:01:4714483 ADD_FAILURE();
14484 return LoadState();
14485 }
14486
dchengb03027d2014-10-21 12:00:2014487 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]bf828982013-08-14 18:01:4714488
dchengb03027d2014-10-21 12:00:2014489 bool was_npn_negotiated() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714490
dchengb03027d2014-10-21 12:00:2014491 NextProto protocol_negotiated() const override { return kProtoUnknown; }
[email protected]bf828982013-08-14 18:01:4714492
dchengb03027d2014-10-21 12:00:2014493 bool using_spdy() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714494
ttuttle1f2d7e92015-04-28 16:17:4714495 const ConnectionAttempts& connection_attempts() const override {
14496 static ConnectionAttempts no_attempts;
14497 return no_attempts;
14498 }
14499
[email protected]bf828982013-08-14 18:01:4714500 private:
14501 RequestPriority priority_;
[email protected]e86839fd2013-08-14 18:29:0314502 HttpStreamRequest::Delegate* const delegate_;
[email protected]831e4a32013-11-14 02:14:4414503 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
[email protected]bf828982013-08-14 18:01:4714504
14505 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
14506};
14507
14508// Fake HttpStreamFactory that vends FakeStreamRequests.
14509class FakeStreamFactory : public HttpStreamFactory {
14510 public:
14511 FakeStreamFactory() {}
dchengb03027d2014-10-21 12:00:2014512 ~FakeStreamFactory() override {}
[email protected]bf828982013-08-14 18:01:4714513
14514 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
14515 // RequestStream() (which may be NULL if it was destroyed already).
14516 base::WeakPtr<FakeStreamRequest> last_stream_request() {
14517 return last_stream_request_;
14518 }
14519
dchengb03027d2014-10-21 12:00:2014520 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
14521 RequestPriority priority,
14522 const SSLConfig& server_ssl_config,
14523 const SSLConfig& proxy_ssl_config,
14524 HttpStreamRequest::Delegate* delegate,
14525 const BoundNetLog& net_log) override {
[email protected]e86839fd2013-08-14 18:29:0314526 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
[email protected]bf828982013-08-14 18:01:4714527 last_stream_request_ = fake_request->AsWeakPtr();
14528 return fake_request;
14529 }
14530
xunjieli11834f02015-12-22 04:27:0814531 HttpStreamRequest* RequestBidirectionalStreamJob(
14532 const HttpRequestInfo& info,
14533 RequestPriority priority,
14534 const SSLConfig& server_ssl_config,
14535 const SSLConfig& proxy_ssl_config,
14536 HttpStreamRequest::Delegate* delegate,
14537 const BoundNetLog& net_log) override {
14538 NOTREACHED();
14539 return nullptr;
14540 }
14541
dchengb03027d2014-10-21 12:00:2014542 HttpStreamRequest* RequestWebSocketHandshakeStream(
[email protected]bf828982013-08-14 18:01:4714543 const HttpRequestInfo& info,
14544 RequestPriority priority,
14545 const SSLConfig& server_ssl_config,
14546 const SSLConfig& proxy_ssl_config,
14547 HttpStreamRequest::Delegate* delegate,
[email protected]467086b2013-11-12 08:19:4614548 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
mostynbba063d6032014-10-09 11:01:1314549 const BoundNetLog& net_log) override {
[email protected]831e4a32013-11-14 02:14:4414550 FakeStreamRequest* fake_request =
14551 new FakeStreamRequest(priority, delegate, create_helper);
14552 last_stream_request_ = fake_request->AsWeakPtr();
14553 return fake_request;
[email protected]bf828982013-08-14 18:01:4714554 }
14555
dchengb03027d2014-10-21 12:00:2014556 void PreconnectStreams(int num_streams,
14557 const HttpRequestInfo& info,
dchengb03027d2014-10-21 12:00:2014558 const SSLConfig& server_ssl_config,
14559 const SSLConfig& proxy_ssl_config) override {
[email protected]bf828982013-08-14 18:01:4714560 ADD_FAILURE();
14561 }
14562
dchengb03027d2014-10-21 12:00:2014563 const HostMappingRules* GetHostMappingRules() const override {
[email protected]bf828982013-08-14 18:01:4714564 ADD_FAILURE();
14565 return NULL;
14566 }
14567
14568 private:
14569 base::WeakPtr<FakeStreamRequest> last_stream_request_;
14570
14571 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
14572};
14573
Adam Rice425cf122015-01-19 06:18:2414574// TODO(ricea): Maybe unify this with the one in
14575// url_request_http_job_unittest.cc ?
14576class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
14577 public:
14578 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection,
14579 bool using_proxy)
14580 : state_(connection.release(), using_proxy) {}
14581
14582 // Fake implementation of HttpStreamBase methods.
14583 // This ends up being quite "real" because this object has to really send data
14584 // on the mock socket. It might be easier to use the real implementation, but
14585 // the fact that the WebSocket code is not compiled on iOS makes that
14586 // difficult.
14587 int InitializeStream(const HttpRequestInfo* request_info,
14588 RequestPriority priority,
14589 const BoundNetLog& net_log,
14590 const CompletionCallback& callback) override {
14591 state_.Initialize(request_info, priority, net_log, callback);
14592 return OK;
14593 }
14594
14595 int SendRequest(const HttpRequestHeaders& request_headers,
14596 HttpResponseInfo* response,
14597 const CompletionCallback& callback) override {
14598 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
14599 response, callback);
14600 }
14601
14602 int ReadResponseHeaders(const CompletionCallback& callback) override {
14603 return parser()->ReadResponseHeaders(callback);
14604 }
14605
14606 int ReadResponseBody(IOBuffer* buf,
14607 int buf_len,
14608 const CompletionCallback& callback) override {
14609 NOTREACHED();
14610 return ERR_IO_PENDING;
14611 }
14612
14613 void Close(bool not_reusable) override {
14614 if (parser())
14615 parser()->Close(true);
14616 }
14617
14618 bool IsResponseBodyComplete() const override {
14619 NOTREACHED();
14620 return false;
14621 }
14622
Adam Rice425cf122015-01-19 06:18:2414623 bool IsConnectionReused() const override {
14624 NOTREACHED();
14625 return false;
14626 }
14627 void SetConnectionReused() override { NOTREACHED(); }
14628
mmenkebd84c392015-09-02 14:12:3414629 bool CanReuseConnection() const override { return false; }
Adam Rice425cf122015-01-19 06:18:2414630
sclittle4de1bab92015-09-22 21:28:2414631 int64_t GetTotalReceivedBytes() const override {
Adam Rice425cf122015-01-19 06:18:2414632 NOTREACHED();
14633 return 0;
14634 }
14635
sclittlebe1ccf62015-09-02 19:40:3614636 int64_t GetTotalSentBytes() const override {
14637 NOTREACHED();
14638 return 0;
14639 }
14640
Adam Rice425cf122015-01-19 06:18:2414641 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
14642 NOTREACHED();
14643 return false;
14644 }
14645
Adam Ricecb76ac62015-02-20 05:33:2514646 void GetSSLInfo(SSLInfo* ssl_info) override {}
Adam Rice425cf122015-01-19 06:18:2414647
14648 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
14649 NOTREACHED();
14650 }
14651
ttuttled9dbc652015-09-29 20:00:5914652 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
14653
nharperb7441ef2016-01-25 23:54:1414654 Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
14655 std::vector<uint8_t>* out) override {
14656 ADD_FAILURE();
14657 return ERR_NOT_IMPLEMENTED;
14658 }
14659
Adam Rice425cf122015-01-19 06:18:2414660 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
14661
zhongyica364fbb2015-12-12 03:39:1214662 void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
14663
Adam Rice425cf122015-01-19 06:18:2414664 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
14665
14666 UploadProgress GetUploadProgress() const override {
14667 NOTREACHED();
14668 return UploadProgress();
14669 }
14670
14671 HttpStream* RenewStreamForAuth() override {
14672 NOTREACHED();
14673 return nullptr;
14674 }
14675
14676 // Fake implementation of WebSocketHandshakeStreamBase method(s)
14677 scoped_ptr<WebSocketStream> Upgrade() override {
14678 NOTREACHED();
14679 return scoped_ptr<WebSocketStream>();
14680 }
14681
14682 private:
14683 HttpStreamParser* parser() const { return state_.parser(); }
14684 HttpBasicState state_;
14685
14686 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
14687};
14688
[email protected]831e4a32013-11-14 02:14:4414689// TODO(yhirano): Split this class out into a net/websockets file, if it is
14690// worth doing.
14691class FakeWebSocketStreamCreateHelper :
14692 public WebSocketHandshakeStreamBase::CreateHelper {
14693 public:
dchengb03027d2014-10-21 12:00:2014694 WebSocketHandshakeStreamBase* CreateBasicStream(
[email protected]7e841a52013-11-22 09:04:2114695 scoped_ptr<ClientSocketHandle> connection,
mostynbba063d6032014-10-09 11:01:1314696 bool using_proxy) override {
dchengc7eeda422015-12-26 03:56:4814697 return new FakeWebSocketBasicHandshakeStream(std::move(connection),
Adam Rice425cf122015-01-19 06:18:2414698 using_proxy);
[email protected]831e4a32013-11-14 02:14:4414699 }
14700
dchengb03027d2014-10-21 12:00:2014701 WebSocketHandshakeStreamBase* CreateSpdyStream(
[email protected]831e4a32013-11-14 02:14:4414702 const base::WeakPtr<SpdySession>& session,
mostynbba063d6032014-10-09 11:01:1314703 bool use_relative_url) override {
[email protected]831e4a32013-11-14 02:14:4414704 NOTREACHED();
14705 return NULL;
14706 };
14707
dchengb03027d2014-10-21 12:00:2014708 ~FakeWebSocketStreamCreateHelper() override {}
[email protected]831e4a32013-11-14 02:14:4414709
14710 virtual scoped_ptr<WebSocketStream> Upgrade() {
14711 NOTREACHED();
14712 return scoped_ptr<WebSocketStream>();
14713 }
14714};
14715
[email protected]bf828982013-08-14 18:01:4714716} // namespace
14717
14718// Make sure that HttpNetworkTransaction passes on its priority to its
14719// stream request on start.
14720TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
mmenkee65e7af2015-10-13 17:16:4214721 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14722 HttpNetworkSessionPeer peer(session.get());
[email protected]bf828982013-08-14 18:01:4714723 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414724 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714725
dcheng48459ac22014-08-26 00:46:4114726 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714727
14728 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
14729
14730 HttpRequestInfo request;
14731 TestCompletionCallback callback;
14732 EXPECT_EQ(ERR_IO_PENDING,
14733 trans.Start(&request, callback.callback(), BoundNetLog()));
14734
14735 base::WeakPtr<FakeStreamRequest> fake_request =
14736 fake_factory->last_stream_request();
14737 ASSERT_TRUE(fake_request != NULL);
14738 EXPECT_EQ(LOW, fake_request->priority());
14739}
14740
14741// Make sure that HttpNetworkTransaction passes on its priority
14742// updates to its stream request.
14743TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
mmenkee65e7af2015-10-13 17:16:4214744 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14745 HttpNetworkSessionPeer peer(session.get());
[email protected]bf828982013-08-14 18:01:4714746 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414747 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714748
dcheng48459ac22014-08-26 00:46:4114749 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714750
14751 HttpRequestInfo request;
14752 TestCompletionCallback callback;
14753 EXPECT_EQ(ERR_IO_PENDING,
14754 trans.Start(&request, callback.callback(), BoundNetLog()));
14755
14756 base::WeakPtr<FakeStreamRequest> fake_request =
14757 fake_factory->last_stream_request();
14758 ASSERT_TRUE(fake_request != NULL);
14759 EXPECT_EQ(LOW, fake_request->priority());
14760
14761 trans.SetPriority(LOWEST);
14762 ASSERT_TRUE(fake_request != NULL);
14763 EXPECT_EQ(LOWEST, fake_request->priority());
14764}
14765
[email protected]e86839fd2013-08-14 18:29:0314766// Make sure that HttpNetworkTransaction passes on its priority
14767// updates to its stream.
14768TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
mmenkee65e7af2015-10-13 17:16:4214769 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14770 HttpNetworkSessionPeer peer(session.get());
[email protected]e86839fd2013-08-14 18:29:0314771 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414772 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]e86839fd2013-08-14 18:29:0314773
dcheng48459ac22014-08-26 00:46:4114774 HttpNetworkTransaction trans(LOW, session.get());
[email protected]e86839fd2013-08-14 18:29:0314775
14776 HttpRequestInfo request;
14777 TestCompletionCallback callback;
14778 EXPECT_EQ(ERR_IO_PENDING,
14779 trans.Start(&request, callback.callback(), BoundNetLog()));
14780
14781 base::WeakPtr<FakeStreamRequest> fake_request =
14782 fake_factory->last_stream_request();
14783 ASSERT_TRUE(fake_request != NULL);
14784 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
14785 ASSERT_TRUE(fake_stream != NULL);
14786 EXPECT_EQ(LOW, fake_stream->priority());
14787
14788 trans.SetPriority(LOWEST);
14789 EXPECT_EQ(LOWEST, fake_stream->priority());
14790}
14791
[email protected]831e4a32013-11-14 02:14:4414792TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
14793 // The same logic needs to be tested for both ws: and wss: schemes, but this
14794 // test is already parameterised on NextProto, so it uses a loop to verify
14795 // that the different schemes work.
bncce36dca22015-04-21 22:11:2314796 std::string test_cases[] = {"ws://www.example.org/",
14797 "wss://www.example.org/"};
[email protected]831e4a32013-11-14 02:14:4414798 for (size_t i = 0; i < arraysize(test_cases); ++i) {
mmenkee65e7af2015-10-13 17:16:4214799 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14800 HttpNetworkSessionPeer peer(session.get());
[email protected]831e4a32013-11-14 02:14:4414801 FakeStreamFactory* fake_factory = new FakeStreamFactory();
14802 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
[email protected]0191b51c2013-11-18 10:55:2314803 peer.SetHttpStreamFactoryForWebSocket(
[email protected]831e4a32013-11-14 02:14:4414804 scoped_ptr<HttpStreamFactory>(fake_factory));
14805
dcheng48459ac22014-08-26 00:46:4114806 HttpNetworkTransaction trans(LOW, session.get());
[email protected]831e4a32013-11-14 02:14:4414807 trans.SetWebSocketHandshakeStreamCreateHelper(
14808 &websocket_stream_create_helper);
14809
14810 HttpRequestInfo request;
14811 TestCompletionCallback callback;
14812 request.method = "GET";
14813 request.url = GURL(test_cases[i]);
14814
14815 EXPECT_EQ(ERR_IO_PENDING,
14816 trans.Start(&request, callback.callback(), BoundNetLog()));
14817
14818 base::WeakPtr<FakeStreamRequest> fake_request =
14819 fake_factory->last_stream_request();
14820 ASSERT_TRUE(fake_request != NULL);
14821 EXPECT_EQ(&websocket_stream_create_helper,
14822 fake_request->websocket_stream_create_helper());
14823 }
14824}
14825
[email protected]043b68c82013-08-22 23:41:5214826// Tests that when a used socket is returned to the SSL socket pool, it's closed
14827// if the transport socket pool is stalled on the global socket limit.
14828TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
14829 ClientSocketPoolManager::set_max_sockets_per_group(
14830 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14831 ClientSocketPoolManager::set_max_sockets_per_pool(
14832 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14833
14834 // Set up SSL request.
14835
14836 HttpRequestInfo ssl_request;
14837 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2314838 ssl_request.url = GURL("https://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214839
14840 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2314841 MockWrite(
14842 "GET / HTTP/1.1\r\n"
14843 "Host: www.example.org\r\n"
14844 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214845 };
14846 MockRead ssl_reads[] = {
14847 MockRead("HTTP/1.1 200 OK\r\n"),
14848 MockRead("Content-Length: 11\r\n\r\n"),
14849 MockRead("hello world"),
14850 MockRead(SYNCHRONOUS, OK),
14851 };
14852 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
14853 ssl_writes, arraysize(ssl_writes));
14854 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
14855
14856 SSLSocketDataProvider ssl(ASYNC, OK);
14857 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14858
14859 // Set up HTTP request.
14860
14861 HttpRequestInfo http_request;
14862 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2314863 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214864
14865 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2314866 MockWrite(
14867 "GET / HTTP/1.1\r\n"
14868 "Host: www.example.org\r\n"
14869 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214870 };
14871 MockRead http_reads[] = {
14872 MockRead("HTTP/1.1 200 OK\r\n"),
14873 MockRead("Content-Length: 7\r\n\r\n"),
14874 MockRead("falafel"),
14875 MockRead(SYNCHRONOUS, OK),
14876 };
14877 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
14878 http_writes, arraysize(http_writes));
14879 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14880
mmenkee65e7af2015-10-13 17:16:4214881 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5214882
14883 // Start the SSL request.
14884 TestCompletionCallback ssl_callback;
14885 scoped_ptr<HttpTransaction> ssl_trans(
14886 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14887 ASSERT_EQ(ERR_IO_PENDING,
14888 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
14889 BoundNetLog()));
14890
14891 // Start the HTTP request. Pool should stall.
14892 TestCompletionCallback http_callback;
14893 scoped_ptr<HttpTransaction> http_trans(
14894 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14895 ASSERT_EQ(ERR_IO_PENDING,
14896 http_trans->Start(&http_request, http_callback.callback(),
14897 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4114898 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214899
14900 // Wait for response from SSL request.
14901 ASSERT_EQ(OK, ssl_callback.WaitForResult());
14902 std::string response_data;
14903 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
14904 EXPECT_EQ("hello world", response_data);
14905
14906 // The SSL socket should automatically be closed, so the HTTP request can
14907 // start.
dcheng48459ac22014-08-26 00:46:4114908 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
14909 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214910
14911 // The HTTP request can now complete.
14912 ASSERT_EQ(OK, http_callback.WaitForResult());
14913 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
14914 EXPECT_EQ("falafel", response_data);
14915
dcheng48459ac22014-08-26 00:46:4114916 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214917}
14918
14919// Tests that when a SSL connection is established but there's no corresponding
14920// request that needs it, the new socket is closed if the transport socket pool
14921// is stalled on the global socket limit.
14922TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
14923 ClientSocketPoolManager::set_max_sockets_per_group(
14924 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14925 ClientSocketPoolManager::set_max_sockets_per_pool(
14926 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14927
14928 // Set up an ssl request.
14929
14930 HttpRequestInfo ssl_request;
14931 ssl_request.method = "GET";
14932 ssl_request.url = GURL("https://www.foopy.com/");
14933
14934 // No data will be sent on the SSL socket.
14935 StaticSocketDataProvider ssl_data;
14936 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
14937
14938 SSLSocketDataProvider ssl(ASYNC, OK);
14939 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14940
14941 // Set up HTTP request.
14942
14943 HttpRequestInfo http_request;
14944 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2314945 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214946
14947 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2314948 MockWrite(
14949 "GET / HTTP/1.1\r\n"
14950 "Host: www.example.org\r\n"
14951 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214952 };
14953 MockRead http_reads[] = {
14954 MockRead("HTTP/1.1 200 OK\r\n"),
14955 MockRead("Content-Length: 7\r\n\r\n"),
14956 MockRead("falafel"),
14957 MockRead(SYNCHRONOUS, OK),
14958 };
14959 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
14960 http_writes, arraysize(http_writes));
14961 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14962
mmenkee65e7af2015-10-13 17:16:4214963 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5214964
14965 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
14966 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2914967 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
14968 SSLConfig ssl_config;
[email protected]043b68c82013-08-22 23:41:5214969 session->ssl_config_service()->GetSSLConfig(&ssl_config);
mmenked1205bd2015-07-15 22:26:3514970 http_stream_factory->PreconnectStreams(1, ssl_request, ssl_config,
14971 ssl_config);
dcheng48459ac22014-08-26 00:46:4114972 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214973
14974 // Start the HTTP request. Pool should stall.
14975 TestCompletionCallback http_callback;
14976 scoped_ptr<HttpTransaction> http_trans(
14977 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14978 ASSERT_EQ(ERR_IO_PENDING,
14979 http_trans->Start(&http_request, http_callback.callback(),
14980 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4114981 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214982
14983 // The SSL connection will automatically be closed once the connection is
14984 // established, to let the HTTP request start.
14985 ASSERT_EQ(OK, http_callback.WaitForResult());
14986 std::string response_data;
14987 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
14988 EXPECT_EQ("falafel", response_data);
14989
dcheng48459ac22014-08-26 00:46:4114990 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214991}
14992
[email protected]02d74a02014-04-23 18:10:5414993TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2214994 std::vector<scoped_ptr<UploadElementReader>> element_readers;
14995 element_readers.push_back(
14996 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
14997 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5414998
14999 HttpRequestInfo request;
15000 request.method = "POST";
15001 request.url = GURL("http://www.foo.com/");
15002 request.upload_data_stream = &upload_data_stream;
15003 request.load_flags = 0;
15004
mmenkee65e7af2015-10-13 17:16:4215005 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415006 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115007 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415008 // Send headers successfully, but get an error while sending the body.
15009 MockWrite data_writes[] = {
15010 MockWrite("POST / HTTP/1.1\r\n"
15011 "Host: www.foo.com\r\n"
15012 "Connection: keep-alive\r\n"
15013 "Content-Length: 3\r\n\r\n"),
15014 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15015 };
15016
15017 MockRead data_reads[] = {
15018 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15019 MockRead("hello world"),
15020 MockRead(SYNCHRONOUS, OK),
15021 };
15022 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15023 arraysize(data_writes));
15024 session_deps_.socket_factory->AddSocketDataProvider(&data);
15025
15026 TestCompletionCallback callback;
15027
15028 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15029 EXPECT_EQ(ERR_IO_PENDING, rv);
15030
15031 rv = callback.WaitForResult();
15032 EXPECT_EQ(OK, rv);
15033
15034 const HttpResponseInfo* response = trans->GetResponseInfo();
15035 ASSERT_TRUE(response != NULL);
15036
15037 EXPECT_TRUE(response->headers.get() != NULL);
15038 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15039
15040 std::string response_data;
15041 rv = ReadTransaction(trans.get(), &response_data);
15042 EXPECT_EQ(OK, rv);
15043 EXPECT_EQ("hello world", response_data);
15044}
15045
15046// This test makes sure the retry logic doesn't trigger when reading an error
15047// response from a server that rejected a POST with a CONNECTION_RESET.
15048TEST_P(HttpNetworkTransactionTest,
15049 PostReadsErrorResponseAfterResetOnReusedSocket) {
mmenkee65e7af2015-10-13 17:16:4215050 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415051 MockWrite data_writes[] = {
15052 MockWrite("GET / HTTP/1.1\r\n"
15053 "Host: www.foo.com\r\n"
15054 "Connection: keep-alive\r\n\r\n"),
15055 MockWrite("POST / HTTP/1.1\r\n"
15056 "Host: www.foo.com\r\n"
15057 "Connection: keep-alive\r\n"
15058 "Content-Length: 3\r\n\r\n"),
15059 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15060 };
15061
15062 MockRead data_reads[] = {
15063 MockRead("HTTP/1.1 200 Peachy\r\n"
15064 "Content-Length: 14\r\n\r\n"),
15065 MockRead("first response"),
15066 MockRead("HTTP/1.1 400 Not OK\r\n"
15067 "Content-Length: 15\r\n\r\n"),
15068 MockRead("second response"),
15069 MockRead(SYNCHRONOUS, OK),
15070 };
15071 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15072 arraysize(data_writes));
15073 session_deps_.socket_factory->AddSocketDataProvider(&data);
15074
15075 TestCompletionCallback callback;
15076 HttpRequestInfo request1;
15077 request1.method = "GET";
15078 request1.url = GURL("http://www.foo.com/");
15079 request1.load_flags = 0;
15080
15081 scoped_ptr<HttpTransaction> trans1(
dcheng48459ac22014-08-26 00:46:4115082 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415083 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
15084 EXPECT_EQ(ERR_IO_PENDING, rv);
15085
15086 rv = callback.WaitForResult();
15087 EXPECT_EQ(OK, rv);
15088
15089 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
15090 ASSERT_TRUE(response1 != NULL);
15091
15092 EXPECT_TRUE(response1->headers.get() != NULL);
15093 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
15094
15095 std::string response_data1;
15096 rv = ReadTransaction(trans1.get(), &response_data1);
15097 EXPECT_EQ(OK, rv);
15098 EXPECT_EQ("first response", response_data1);
15099 // Delete the transaction to release the socket back into the socket pool.
15100 trans1.reset();
15101
olli.raula6df48b2a2015-11-26 07:40:2215102 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15103 element_readers.push_back(
15104 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15105 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415106
15107 HttpRequestInfo request2;
15108 request2.method = "POST";
15109 request2.url = GURL("http://www.foo.com/");
15110 request2.upload_data_stream = &upload_data_stream;
15111 request2.load_flags = 0;
15112
15113 scoped_ptr<HttpTransaction> trans2(
dcheng48459ac22014-08-26 00:46:4115114 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415115 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
15116 EXPECT_EQ(ERR_IO_PENDING, rv);
15117
15118 rv = callback.WaitForResult();
15119 EXPECT_EQ(OK, rv);
15120
15121 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
15122 ASSERT_TRUE(response2 != NULL);
15123
15124 EXPECT_TRUE(response2->headers.get() != NULL);
15125 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
15126
15127 std::string response_data2;
15128 rv = ReadTransaction(trans2.get(), &response_data2);
15129 EXPECT_EQ(OK, rv);
15130 EXPECT_EQ("second response", response_data2);
15131}
15132
15133TEST_P(HttpNetworkTransactionTest,
15134 PostReadsErrorResponseAfterResetPartialBodySent) {
olli.raula6df48b2a2015-11-26 07:40:2215135 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15136 element_readers.push_back(
15137 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15138 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415139
15140 HttpRequestInfo request;
15141 request.method = "POST";
15142 request.url = GURL("http://www.foo.com/");
15143 request.upload_data_stream = &upload_data_stream;
15144 request.load_flags = 0;
15145
mmenkee65e7af2015-10-13 17:16:4215146 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415147 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115148 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415149 // Send headers successfully, but get an error while sending the body.
15150 MockWrite data_writes[] = {
15151 MockWrite("POST / HTTP/1.1\r\n"
15152 "Host: www.foo.com\r\n"
15153 "Connection: keep-alive\r\n"
15154 "Content-Length: 3\r\n\r\n"
15155 "fo"),
15156 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15157 };
15158
15159 MockRead data_reads[] = {
15160 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15161 MockRead("hello world"),
15162 MockRead(SYNCHRONOUS, OK),
15163 };
15164 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15165 arraysize(data_writes));
15166 session_deps_.socket_factory->AddSocketDataProvider(&data);
15167
15168 TestCompletionCallback callback;
15169
15170 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15171 EXPECT_EQ(ERR_IO_PENDING, rv);
15172
15173 rv = callback.WaitForResult();
15174 EXPECT_EQ(OK, rv);
15175
15176 const HttpResponseInfo* response = trans->GetResponseInfo();
15177 ASSERT_TRUE(response != NULL);
15178
15179 EXPECT_TRUE(response->headers.get() != NULL);
15180 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15181
15182 std::string response_data;
15183 rv = ReadTransaction(trans.get(), &response_data);
15184 EXPECT_EQ(OK, rv);
15185 EXPECT_EQ("hello world", response_data);
15186}
15187
15188// This tests the more common case than the previous test, where headers and
15189// body are not merged into a single request.
15190TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0715191 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5415192
15193 HttpRequestInfo request;
15194 request.method = "POST";
15195 request.url = GURL("http://www.foo.com/");
15196 request.upload_data_stream = &upload_data_stream;
15197 request.load_flags = 0;
15198
mmenkee65e7af2015-10-13 17:16:4215199 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415200 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115201 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415202 // Send headers successfully, but get an error while sending the body.
15203 MockWrite data_writes[] = {
15204 MockWrite("POST / HTTP/1.1\r\n"
15205 "Host: www.foo.com\r\n"
15206 "Connection: keep-alive\r\n"
15207 "Transfer-Encoding: chunked\r\n\r\n"),
15208 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15209 };
15210
15211 MockRead data_reads[] = {
15212 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15213 MockRead("hello world"),
15214 MockRead(SYNCHRONOUS, OK),
15215 };
15216 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15217 arraysize(data_writes));
15218 session_deps_.socket_factory->AddSocketDataProvider(&data);
15219
15220 TestCompletionCallback callback;
15221
15222 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15223 EXPECT_EQ(ERR_IO_PENDING, rv);
15224 // Make sure the headers are sent before adding a chunk. This ensures that
15225 // they can't be merged with the body in a single send. Not currently
15226 // necessary since a chunked body is never merged with headers, but this makes
15227 // the test more future proof.
15228 base::RunLoop().RunUntilIdle();
15229
mmenkecbc2b712014-10-09 20:29:0715230 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5415231
15232 rv = callback.WaitForResult();
15233 EXPECT_EQ(OK, rv);
15234
15235 const HttpResponseInfo* response = trans->GetResponseInfo();
15236 ASSERT_TRUE(response != NULL);
15237
15238 EXPECT_TRUE(response->headers.get() != NULL);
15239 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15240
15241 std::string response_data;
15242 rv = ReadTransaction(trans.get(), &response_data);
15243 EXPECT_EQ(OK, rv);
15244 EXPECT_EQ("hello world", response_data);
15245}
15246
15247TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
olli.raula6df48b2a2015-11-26 07:40:2215248 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15249 element_readers.push_back(
15250 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15251 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415252
15253 HttpRequestInfo request;
15254 request.method = "POST";
15255 request.url = GURL("http://www.foo.com/");
15256 request.upload_data_stream = &upload_data_stream;
15257 request.load_flags = 0;
15258
mmenkee65e7af2015-10-13 17:16:4215259 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415260 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115261 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415262
15263 MockWrite data_writes[] = {
15264 MockWrite("POST / HTTP/1.1\r\n"
15265 "Host: www.foo.com\r\n"
15266 "Connection: keep-alive\r\n"
15267 "Content-Length: 3\r\n\r\n"),
15268 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15269 };
15270
15271 MockRead data_reads[] = {
15272 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
15273 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15274 MockRead("hello world"),
15275 MockRead(SYNCHRONOUS, OK),
15276 };
15277 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15278 arraysize(data_writes));
15279 session_deps_.socket_factory->AddSocketDataProvider(&data);
15280
15281 TestCompletionCallback callback;
15282
15283 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15284 EXPECT_EQ(ERR_IO_PENDING, rv);
15285
15286 rv = callback.WaitForResult();
15287 EXPECT_EQ(OK, rv);
15288
15289 const HttpResponseInfo* response = trans->GetResponseInfo();
15290 ASSERT_TRUE(response != NULL);
15291
15292 EXPECT_TRUE(response->headers.get() != NULL);
15293 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15294
15295 std::string response_data;
15296 rv = ReadTransaction(trans.get(), &response_data);
15297 EXPECT_EQ(OK, rv);
15298 EXPECT_EQ("hello world", response_data);
15299}
15300
15301TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215302 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15303 element_readers.push_back(
15304 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15305 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415306
15307 HttpRequestInfo request;
15308 request.method = "POST";
15309 request.url = GURL("http://www.foo.com/");
15310 request.upload_data_stream = &upload_data_stream;
15311 request.load_flags = 0;
15312
mmenkee65e7af2015-10-13 17:16:4215313 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415314 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115315 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415316 // Send headers successfully, but get an error while sending the body.
15317 MockWrite data_writes[] = {
15318 MockWrite("POST / HTTP/1.1\r\n"
15319 "Host: www.foo.com\r\n"
15320 "Connection: keep-alive\r\n"
15321 "Content-Length: 3\r\n\r\n"),
15322 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15323 };
15324
15325 MockRead data_reads[] = {
15326 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
15327 MockRead("hello world"),
15328 MockRead(SYNCHRONOUS, OK),
15329 };
15330 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15331 arraysize(data_writes));
15332 session_deps_.socket_factory->AddSocketDataProvider(&data);
15333
15334 TestCompletionCallback callback;
15335
15336 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15337 EXPECT_EQ(ERR_IO_PENDING, rv);
15338
15339 rv = callback.WaitForResult();
15340 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415341}
15342
15343TEST_P(HttpNetworkTransactionTest,
15344 PostIgnoresNonErrorResponseAfterResetAnd100) {
olli.raula6df48b2a2015-11-26 07:40:2215345 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15346 element_readers.push_back(
15347 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15348 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415349
15350 HttpRequestInfo request;
15351 request.method = "POST";
15352 request.url = GURL("http://www.foo.com/");
15353 request.upload_data_stream = &upload_data_stream;
15354 request.load_flags = 0;
15355
mmenkee65e7af2015-10-13 17:16:4215356 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415357 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115358 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415359 // Send headers successfully, but get an error while sending the body.
15360 MockWrite data_writes[] = {
15361 MockWrite("POST / HTTP/1.1\r\n"
15362 "Host: www.foo.com\r\n"
15363 "Connection: keep-alive\r\n"
15364 "Content-Length: 3\r\n\r\n"),
15365 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15366 };
15367
15368 MockRead data_reads[] = {
15369 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
15370 MockRead("HTTP/1.0 302 Redirect\r\n"),
15371 MockRead("Location: http://somewhere-else.com/\r\n"),
15372 MockRead("Content-Length: 0\r\n\r\n"),
15373 MockRead(SYNCHRONOUS, OK),
15374 };
15375 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15376 arraysize(data_writes));
15377 session_deps_.socket_factory->AddSocketDataProvider(&data);
15378
15379 TestCompletionCallback callback;
15380
15381 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15382 EXPECT_EQ(ERR_IO_PENDING, rv);
15383
15384 rv = callback.WaitForResult();
15385 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415386}
15387
15388TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215389 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15390 element_readers.push_back(
15391 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15392 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415393
15394 HttpRequestInfo request;
15395 request.method = "POST";
15396 request.url = GURL("http://www.foo.com/");
15397 request.upload_data_stream = &upload_data_stream;
15398 request.load_flags = 0;
15399
mmenkee65e7af2015-10-13 17:16:4215400 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415401 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115402 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415403 // Send headers successfully, but get an error while sending the body.
15404 MockWrite data_writes[] = {
15405 MockWrite("POST / HTTP/1.1\r\n"
15406 "Host: www.foo.com\r\n"
15407 "Connection: keep-alive\r\n"
15408 "Content-Length: 3\r\n\r\n"),
15409 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15410 };
15411
15412 MockRead data_reads[] = {
15413 MockRead("HTTP 0.9 rocks!"),
15414 MockRead(SYNCHRONOUS, OK),
15415 };
15416 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15417 arraysize(data_writes));
15418 session_deps_.socket_factory->AddSocketDataProvider(&data);
15419
15420 TestCompletionCallback callback;
15421
15422 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15423 EXPECT_EQ(ERR_IO_PENDING, rv);
15424
15425 rv = callback.WaitForResult();
15426 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415427}
15428
15429TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215430 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15431 element_readers.push_back(
15432 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15433 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415434
15435 HttpRequestInfo request;
15436 request.method = "POST";
15437 request.url = GURL("http://www.foo.com/");
15438 request.upload_data_stream = &upload_data_stream;
15439 request.load_flags = 0;
15440
mmenkee65e7af2015-10-13 17:16:4215441 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415442 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115443 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415444 // Send headers successfully, but get an error while sending the body.
15445 MockWrite data_writes[] = {
15446 MockWrite("POST / HTTP/1.1\r\n"
15447 "Host: www.foo.com\r\n"
15448 "Connection: keep-alive\r\n"
15449 "Content-Length: 3\r\n\r\n"),
15450 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15451 };
15452
15453 MockRead data_reads[] = {
15454 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
15455 MockRead(SYNCHRONOUS, OK),
15456 };
15457 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15458 arraysize(data_writes));
15459 session_deps_.socket_factory->AddSocketDataProvider(&data);
15460
15461 TestCompletionCallback callback;
15462
15463 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15464 EXPECT_EQ(ERR_IO_PENDING, rv);
15465
15466 rv = callback.WaitForResult();
15467 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415468}
15469
Adam Rice425cf122015-01-19 06:18:2415470// Verify that proxy headers are not sent to the destination server when
15471// establishing a tunnel for a secure WebSocket connection.
15472TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
15473 HttpRequestInfo request;
15474 request.method = "GET";
bncce36dca22015-04-21 22:11:2315475 request.url = GURL("wss://www.example.org/");
Adam Rice425cf122015-01-19 06:18:2415476 AddWebSocketHeaders(&request.extra_headers);
15477
15478 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:0315479 session_deps_.proxy_service =
15480 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
Adam Rice425cf122015-01-19 06:18:2415481
mmenkee65e7af2015-10-13 17:16:4215482 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2415483
15484 // Since a proxy is configured, try to establish a tunnel.
15485 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1715486 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15487 "Host: www.example.org:443\r\n"
15488 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415489
15490 // After calling trans->RestartWithAuth(), this is the request we should
15491 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1715492 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15493 "Host: www.example.org:443\r\n"
15494 "Proxy-Connection: keep-alive\r\n"
15495 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415496
rsleevidb16bb02015-11-12 23:47:1715497 MockWrite("GET / HTTP/1.1\r\n"
15498 "Host: www.example.org\r\n"
15499 "Connection: Upgrade\r\n"
15500 "Upgrade: websocket\r\n"
15501 "Origin: http://www.example.org\r\n"
15502 "Sec-WebSocket-Version: 13\r\n"
15503 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415504 };
15505
15506 // The proxy responds to the connect with a 407, using a persistent
15507 // connection.
15508 MockRead data_reads[] = {
15509 // No credentials.
15510 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
15511 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
mmenkee71e15332015-10-07 16:39:5415512 MockRead("Content-Length: 0\r\n"),
15513 MockRead("Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415514
15515 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15516
15517 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15518 MockRead("Upgrade: websocket\r\n"),
15519 MockRead("Connection: Upgrade\r\n"),
15520 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15521 };
15522
15523 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15524 arraysize(data_writes));
15525 session_deps_.socket_factory->AddSocketDataProvider(&data);
15526 SSLSocketDataProvider ssl(ASYNC, OK);
15527 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15528
15529 scoped_ptr<HttpTransaction> trans(
15530 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15531 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15532 trans->SetWebSocketHandshakeStreamCreateHelper(
15533 &websocket_stream_create_helper);
15534
15535 {
15536 TestCompletionCallback callback;
15537
15538 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15539 EXPECT_EQ(ERR_IO_PENDING, rv);
15540
15541 rv = callback.WaitForResult();
15542 EXPECT_EQ(OK, rv);
15543 }
15544
15545 const HttpResponseInfo* response = trans->GetResponseInfo();
15546 ASSERT_TRUE(response);
15547 ASSERT_TRUE(response->headers.get());
15548 EXPECT_EQ(407, response->headers->response_code());
15549
15550 {
15551 TestCompletionCallback callback;
15552
15553 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
15554 callback.callback());
15555 EXPECT_EQ(ERR_IO_PENDING, rv);
15556
15557 rv = callback.WaitForResult();
15558 EXPECT_EQ(OK, rv);
15559 }
15560
15561 response = trans->GetResponseInfo();
15562 ASSERT_TRUE(response);
15563 ASSERT_TRUE(response->headers.get());
15564
15565 EXPECT_EQ(101, response->headers->response_code());
15566
15567 trans.reset();
15568 session->CloseAllConnections();
15569}
15570
15571// Verify that proxy headers are not sent to the destination server when
15572// establishing a tunnel for an insecure WebSocket connection.
15573// This requires the authentication info to be injected into the auth cache
15574// due to crbug.com/395064
15575// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
15576TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
15577 HttpRequestInfo request;
15578 request.method = "GET";
bncce36dca22015-04-21 22:11:2315579 request.url = GURL("ws://www.example.org/");
Adam Rice425cf122015-01-19 06:18:2415580 AddWebSocketHeaders(&request.extra_headers);
15581
15582 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:0315583 session_deps_.proxy_service =
15584 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
Adam Rice425cf122015-01-19 06:18:2415585
mmenkee65e7af2015-10-13 17:16:4215586 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2415587
15588 MockWrite data_writes[] = {
15589 // Try to establish a tunnel for the WebSocket connection, with
15590 // credentials. Because WebSockets have a separate set of socket pools,
15591 // they cannot and will not use the same TCP/IP connection as the
15592 // preflight HTTP request.
15593 MockWrite(
bncce36dca22015-04-21 22:11:2315594 "CONNECT www.example.org:80 HTTP/1.1\r\n"
15595 "Host: www.example.org:80\r\n"
Adam Rice425cf122015-01-19 06:18:2415596 "Proxy-Connection: keep-alive\r\n"
15597 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
15598
15599 MockWrite(
15600 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2315601 "Host: www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415602 "Connection: Upgrade\r\n"
15603 "Upgrade: websocket\r\n"
bncce36dca22015-04-21 22:11:2315604 "Origin: http://www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415605 "Sec-WebSocket-Version: 13\r\n"
15606 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
15607 };
15608
15609 MockRead data_reads[] = {
15610 // HTTP CONNECT with credentials.
15611 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15612
15613 // WebSocket connection established inside tunnel.
15614 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15615 MockRead("Upgrade: websocket\r\n"),
15616 MockRead("Connection: Upgrade\r\n"),
15617 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15618 };
15619
15620 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15621 arraysize(data_writes));
15622 session_deps_.socket_factory->AddSocketDataProvider(&data);
15623
15624 session->http_auth_cache()->Add(
15625 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
15626 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
15627
15628 scoped_ptr<HttpTransaction> trans(
15629 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15630 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15631 trans->SetWebSocketHandshakeStreamCreateHelper(
15632 &websocket_stream_create_helper);
15633
15634 TestCompletionCallback callback;
15635
15636 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15637 EXPECT_EQ(ERR_IO_PENDING, rv);
15638
15639 rv = callback.WaitForResult();
15640 EXPECT_EQ(OK, rv);
15641
15642 const HttpResponseInfo* response = trans->GetResponseInfo();
15643 ASSERT_TRUE(response);
15644 ASSERT_TRUE(response->headers.get());
15645
15646 EXPECT_EQ(101, response->headers->response_code());
15647
15648 trans.reset();
15649 session->CloseAllConnections();
15650}
15651
sclittlefb249892015-09-10 21:33:2215652TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
olli.raula6df48b2a2015-11-26 07:40:2215653 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15654 element_readers.push_back(
15655 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15656 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2215657
15658 HttpRequestInfo request;
15659 request.method = "POST";
15660 request.url = GURL("http://www.foo.com/");
15661 request.upload_data_stream = &upload_data_stream;
15662
mmenkee65e7af2015-10-13 17:16:4215663 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215664 scoped_ptr<HttpTransaction> trans(
15665 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15666 MockWrite data_writes[] = {
15667 MockWrite("POST / HTTP/1.1\r\n"
15668 "Host: www.foo.com\r\n"
15669 "Connection: keep-alive\r\n"
15670 "Content-Length: 3\r\n\r\n"),
15671 MockWrite("foo"),
15672 };
15673
15674 MockRead data_reads[] = {
15675 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15676 MockRead(SYNCHRONOUS, OK),
15677 };
15678 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15679 arraysize(data_writes));
15680 session_deps_.socket_factory->AddSocketDataProvider(&data);
15681
15682 TestCompletionCallback callback;
15683
15684 EXPECT_EQ(ERR_IO_PENDING,
15685 trans->Start(&request, callback.callback(), BoundNetLog()));
15686 EXPECT_EQ(OK, callback.WaitForResult());
15687
15688 std::string response_data;
15689 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15690
15691 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15692 trans->GetTotalSentBytes());
15693 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15694 trans->GetTotalReceivedBytes());
15695}
15696
15697TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
olli.raula6df48b2a2015-11-26 07:40:2215698 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15699 element_readers.push_back(
15700 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15701 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2215702
15703 HttpRequestInfo request;
15704 request.method = "POST";
15705 request.url = GURL("http://www.foo.com/");
15706 request.upload_data_stream = &upload_data_stream;
15707
mmenkee65e7af2015-10-13 17:16:4215708 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215709 scoped_ptr<HttpTransaction> trans(
15710 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15711 MockWrite data_writes[] = {
15712 MockWrite("POST / HTTP/1.1\r\n"
15713 "Host: www.foo.com\r\n"
15714 "Connection: keep-alive\r\n"
15715 "Content-Length: 3\r\n\r\n"),
15716 MockWrite("foo"),
15717 };
15718
15719 MockRead data_reads[] = {
15720 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
15721 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15722 MockRead(SYNCHRONOUS, OK),
15723 };
15724 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15725 arraysize(data_writes));
15726 session_deps_.socket_factory->AddSocketDataProvider(&data);
15727
15728 TestCompletionCallback callback;
15729
15730 EXPECT_EQ(ERR_IO_PENDING,
15731 trans->Start(&request, callback.callback(), BoundNetLog()));
15732 EXPECT_EQ(OK, callback.WaitForResult());
15733
15734 std::string response_data;
15735 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15736
15737 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15738 trans->GetTotalSentBytes());
15739 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15740 trans->GetTotalReceivedBytes());
15741}
15742
15743TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2215744 ChunkedUploadDataStream upload_data_stream(0);
15745
15746 HttpRequestInfo request;
15747 request.method = "POST";
15748 request.url = GURL("http://www.foo.com/");
15749 request.upload_data_stream = &upload_data_stream;
15750
mmenkee65e7af2015-10-13 17:16:4215751 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215752 scoped_ptr<HttpTransaction> trans(
15753 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15754 // Send headers successfully, but get an error while sending the body.
15755 MockWrite data_writes[] = {
15756 MockWrite("POST / HTTP/1.1\r\n"
15757 "Host: www.foo.com\r\n"
15758 "Connection: keep-alive\r\n"
15759 "Transfer-Encoding: chunked\r\n\r\n"),
15760 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
15761 };
15762
15763 MockRead data_reads[] = {
15764 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15765 MockRead(SYNCHRONOUS, OK),
15766 };
15767 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15768 arraysize(data_writes));
15769 session_deps_.socket_factory->AddSocketDataProvider(&data);
15770
15771 TestCompletionCallback callback;
15772
15773 EXPECT_EQ(ERR_IO_PENDING,
15774 trans->Start(&request, callback.callback(), BoundNetLog()));
15775
15776 base::RunLoop().RunUntilIdle();
15777 upload_data_stream.AppendData("f", 1, false);
15778
15779 base::RunLoop().RunUntilIdle();
15780 upload_data_stream.AppendData("oo", 2, true);
15781
15782 EXPECT_EQ(OK, callback.WaitForResult());
15783
15784 std::string response_data;
15785 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15786
15787 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15788 trans->GetTotalSentBytes());
15789 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15790 trans->GetTotalReceivedBytes());
15791}
15792
bncf4588402015-11-24 13:33:1815793TEST_P(HttpNetworkTransactionTest, EnableNPN) {
15794 session_deps_.next_protos = NextProtosDefaults();
15795 session_deps_.enable_npn = true;
15796
15797 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15798 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15799
15800 EXPECT_THAT(trans.server_ssl_config_.alpn_protos,
15801 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15802 EXPECT_THAT(trans.server_ssl_config_.npn_protos,
15803 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15804}
15805
15806TEST_P(HttpNetworkTransactionTest, DisableNPN) {
15807 session_deps_.next_protos = NextProtosDefaults();
15808 session_deps_.enable_npn = false;
15809
15810 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15811 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15812
15813 EXPECT_THAT(trans.server_ssl_config_.alpn_protos,
15814 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15815 EXPECT_TRUE(trans.server_ssl_config_.npn_protos.empty());
15816}
15817
nharperb7441ef2016-01-25 23:54:1415818#if !defined(OS_IOS)
15819TEST_P(HttpNetworkTransactionTest, TokenBindingSpdy) {
15820 const std::string https_url = "https://www.example.com";
15821 HttpRequestInfo request;
15822 request.url = GURL(https_url);
15823 request.method = "GET";
15824
15825 SSLSocketDataProvider ssl(ASYNC, OK);
15826 ssl.token_binding_negotiated = true;
15827 ssl.token_binding_key_param = TB_PARAM_ECDSAP256;
15828 ssl.SetNextProto(GetProtocol());
15829 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15830
15831 scoped_ptr<SpdyFrame> resp(
15832 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
15833 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
15834 MockRead reads[] = {CreateMockRead(*resp), CreateMockRead(*body),
15835 MockRead(ASYNC, ERR_IO_PENDING)};
15836 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
15837 session_deps_.socket_factory->AddSocketDataProvider(&data);
15838 session_deps_.channel_id_service.reset(new ChannelIDService(
15839 new DefaultChannelIDStore(nullptr), base::ThreadTaskRunnerHandle::Get()));
15840 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15841
15842 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15843 TestCompletionCallback callback;
15844 EXPECT_EQ(ERR_IO_PENDING,
15845 trans.Start(&request, callback.callback(), BoundNetLog()));
15846 base::MessageLoop::current()->RunUntilIdle();
15847
15848 EXPECT_TRUE(trans.GetResponseInfo()->was_fetched_via_spdy);
15849 HttpRequestHeaders headers;
15850 ASSERT_TRUE(trans.GetFullRequestHeaders(&headers));
15851 EXPECT_TRUE(headers.HasHeader(HttpRequestHeaders::kTokenBinding));
15852}
15853#endif // !defined(OS_IOS)
15854
[email protected]89ceba9a2009-03-21 03:46:0615855} // namespace net