blob: 758b32eedab9cb3ba3dc1c8e9cff36f1807cfaf8 [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"
mmenked3641e12016-01-28 16:06:1568#include "net/socket/client_socket_pool.h"
[email protected]483fa202013-05-14 01:07:0369#include "net/socket/client_socket_pool_manager.h"
ttuttle1f2d7e92015-04-28 16:17:4770#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0271#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0772#include "net/socket/next_proto.h"
[email protected]f7984fc62009-06-22 23:26:4473#include "net/socket/socket_test_util.h"
74#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5475#include "net/spdy/spdy_framer.h"
76#include "net/spdy/spdy_session.h"
77#include "net/spdy/spdy_session_pool.h"
[email protected]23e482282013-06-14 16:08:0278#include "net/spdy/spdy_test_util_common.h"
nharperb7441ef2016-01-25 23:54:1479#include "net/ssl/default_channel_id_store.h"
[email protected]536fd0b2013-03-14 17:41:5780#include "net/ssl/ssl_cert_request_info.h"
[email protected]e86839fd2013-08-14 18:29:0381#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:5782#include "net/ssl/ssl_config_service_defaults.h"
83#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:5484#include "net/ssl/ssl_private_key.h"
[email protected]6e7845ae2013-03-29 21:48:1185#include "net/test/cert_test_util.h"
[email protected]831e4a32013-11-14 02:14:4486#include "net/websockets/websocket_handshake_stream_base.h"
bncf4588402015-11-24 13:33:1887#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:5288#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1589#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:2790#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:5291
[email protected]ad65a3e2013-12-25 18:18:0192using base::ASCIIToUTF16;
93
initial.commit586acc5fe2008-07-26 22:42:5294//-----------------------------------------------------------------------------
95
ttuttle859dc7a2015-04-23 19:42:2996namespace net {
97
[email protected]13c8a092010-07-29 06:15:4498namespace {
99
rdsmithebb50aa2015-11-12 03:44:38100enum TestCase {
101 // Test using the SPDY/3.1 protocol.
102 kTestCaseSPDY31,
103
104 // Test using the HTTP/2 protocol, without specifying a stream
105 // dependency based on the RequestPriority.
106 kTestCaseHTTP2NoPriorityDependencies,
107
108 // Test using the HTTP/2 protocol, specifying a stream
109 // dependency based on the RequestPriority.
110 kTestCaseHTTP2PriorityDependencies
111};
112
[email protected]42cba2fb2013-03-29 19:58:57113const base::string16 kBar(ASCIIToUTF16("bar"));
114const base::string16 kBar2(ASCIIToUTF16("bar2"));
115const base::string16 kBar3(ASCIIToUTF16("bar3"));
116const base::string16 kBaz(ASCIIToUTF16("baz"));
117const base::string16 kFirst(ASCIIToUTF16("first"));
118const base::string16 kFoo(ASCIIToUTF16("foo"));
119const base::string16 kFoo2(ASCIIToUTF16("foo2"));
120const base::string16 kFoo3(ASCIIToUTF16("foo3"));
121const base::string16 kFou(ASCIIToUTF16("fou"));
122const base::string16 kSecond(ASCIIToUTF16("second"));
123const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
124const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44125
ttuttle859dc7a2015-04-23 19:42:29126int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
127 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
128 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02129}
130
ttuttle859dc7a2015-04-23 19:42:29131int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession* session) {
132 return session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
133 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02134}
135
ttuttle859dc7a2015-04-23 19:42:29136bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
137 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
138 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52139}
140
[email protected]f3da152d2012-06-02 01:00:57141// Takes in a Value created from a NetLogHttpResponseParameter, and returns
142// a JSONified list of headers as a single string. Uses single quotes instead
143// of double quotes for easier comparison. Returns false on failure.
[email protected]ea5ef4c2013-06-13 22:50:27144bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
[email protected]f3da152d2012-06-02 01:00:57145 if (!params)
146 return false;
[email protected]ea5ef4c2013-06-13 22:50:27147 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:57148 if (!params->GetList("headers", &header_list))
149 return false;
150 std::string double_quote_headers;
estade8d046462015-05-16 01:02:34151 base::JSONWriter::Write(*header_list, &double_quote_headers);
[email protected]466c9862013-12-03 22:05:28152 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
[email protected]f3da152d2012-06-02 01:00:57153 return true;
154}
155
[email protected]029c83b62013-01-24 05:28:20156// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
157// used.
ttuttle859dc7a2015-04-23 19:42:29158void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20159 EXPECT_TRUE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29160 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25161
[email protected]029c83b62013-01-24 05:28:20162 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
163 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
164
ttuttle859dc7a2015-04-23 19:42:29165 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20166 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25167
168 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25169
[email protected]3b23a222013-05-15 21:33:25170 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25171 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
172 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25173 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25174}
175
[email protected]029c83b62013-01-24 05:28:20176// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
177// used.
ttuttle859dc7a2015-04-23 19:42:29178void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25179 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20180 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29181 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20182
183 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
184 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
185
ttuttle859dc7a2015-04-23 19:42:29186 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
187 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20188 EXPECT_LE(load_timing_info.connect_timing.connect_end,
189 load_timing_info.send_start);
190
191 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20192
[email protected]3b23a222013-05-15 21:33:25193 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20194 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
195 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25196 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20197}
198
199// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
200// used.
ttuttle859dc7a2015-04-23 19:42:29201void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20202 EXPECT_TRUE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29203 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20204
ttuttle859dc7a2015-04-23 19:42:29205 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20206
207 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
208 EXPECT_LE(load_timing_info.proxy_resolve_start,
209 load_timing_info.proxy_resolve_end);
210 EXPECT_LE(load_timing_info.proxy_resolve_end,
211 load_timing_info.send_start);
212 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20213
[email protected]3b23a222013-05-15 21:33:25214 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20215 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
216 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25217 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20218}
219
220// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
221// used.
ttuttle859dc7a2015-04-23 19:42:29222void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20223 int connect_timing_flags) {
224 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29225 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20226
227 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
228 EXPECT_LE(load_timing_info.proxy_resolve_start,
229 load_timing_info.proxy_resolve_end);
230 EXPECT_LE(load_timing_info.proxy_resolve_end,
231 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29232 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
233 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20234 EXPECT_LE(load_timing_info.connect_timing.connect_end,
235 load_timing_info.send_start);
236
237 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20238
[email protected]3b23a222013-05-15 21:33:25239 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20240 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
241 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25242 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25243}
244
ttuttle859dc7a2015-04-23 19:42:29245void AddWebSocketHeaders(HttpRequestHeaders* headers) {
Adam Rice425cf122015-01-19 06:18:24246 headers->SetHeader("Connection", "Upgrade");
247 headers->SetHeader("Upgrade", "websocket");
bncce36dca22015-04-21 22:11:23248 headers->SetHeader("Origin", "http://www.example.org");
Adam Rice425cf122015-01-19 06:18:24249 headers->SetHeader("Sec-WebSocket-Version", "13");
250 headers->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
251}
252
mmenkee65e7af2015-10-13 17:16:42253scoped_ptr<HttpNetworkSession> CreateSession(
254 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34255 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14256}
257
[email protected]448d4ca52012-03-04 04:12:23258} // namespace
259
[email protected]23e482282013-06-14 16:08:02260class HttpNetworkTransactionTest
261 : public PlatformTest,
rdsmithebb50aa2015-11-12 03:44:38262 public ::testing::WithParamInterface<TestCase> {
[email protected]483fa202013-05-14 01:07:03263 public:
[email protected]23e482282013-06-14 16:08:02264 virtual ~HttpNetworkTransactionTest() {
[email protected]483fa202013-05-14 01:07:03265 // Important to restore the per-pool limit first, since the pool limit must
266 // always be greater than group limit, and the tests reduce both limits.
267 ClientSocketPoolManager::set_max_sockets_per_pool(
268 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
269 ClientSocketPoolManager::set_max_sockets_per_group(
270 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
rdsmithebb50aa2015-11-12 03:44:38271 SpdySession::SetPriorityDependencyDefaultForTesting(false);
[email protected]483fa202013-05-14 01:07:03272 }
273
[email protected]e3ceb682011-06-28 23:55:46274 protected:
[email protected]23e482282013-06-14 16:08:02275 HttpNetworkTransactionTest()
rdsmithebb50aa2015-11-12 03:44:38276 : spdy_util_(GetProtocol(), GetDependenciesFromPriority()),
277 session_deps_(GetProtocol()),
[email protected]483fa202013-05-14 01:07:03278 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
279 HttpNetworkSession::NORMAL_SOCKET_POOL)),
280 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
281 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
rdsmithebb50aa2015-11-12 03:44:38282 SpdySession::SetPriorityDependencyDefaultForTesting(
283 GetDependenciesFromPriority());
[email protected]483fa202013-05-14 01:07:03284 }
[email protected]bb88e1d32013-05-03 23:11:07285
[email protected]e3ceb682011-06-28 23:55:46286 struct SimpleGetHelperResult {
287 int rv;
288 std::string status_line;
289 std::string response_data;
sclittlefb249892015-09-10 21:33:22290 int64_t total_received_bytes;
291 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25292 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47293 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59294 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46295 };
296
dcheng67be2b1f2014-10-27 21:47:29297 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50298 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34299 base::MessageLoop::current()->RunUntilIdle();
[email protected]2ff8b312010-04-26 22:20:54300 }
301
dcheng67be2b1f2014-10-27 21:47:29302 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50303 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34304 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09305 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:34306 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09307 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50308 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34309 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09310 }
311
rdsmithebb50aa2015-11-12 03:44:38312 NextProto GetProtocol() const {
313 return GetParam() == kTestCaseSPDY31 ? kProtoSPDY31 : kProtoHTTP2;
314 }
315
316 bool GetDependenciesFromPriority() const {
317 return GetParam() == kTestCaseHTTP2PriorityDependencies;
318 }
319
bnc33b8cef42014-11-19 17:30:38320 const char* GetAlternateProtocolFromParam() {
rdsmithebb50aa2015-11-12 03:44:38321 return AlternateProtocolToString(
322 AlternateProtocolFromNextProto(GetProtocol()));
bnc33b8cef42014-11-19 17:30:38323 }
324
bncc958faa2015-07-31 18:14:52325 std::string GetAlternativeServiceHttpHeader() {
326 return std::string("Alt-Svc: ") + GetAlternateProtocolFromParam() +
327 "=\"www.example.com:443\"\r\n";
328 }
329
[email protected]8a0fc822013-06-27 20:52:43330 std::string GetAlternateProtocolHttpHeader() {
bnc33b8cef42014-11-19 17:30:38331 return std::string("Alternate-Protocol: 443:") +
bncc958faa2015-07-31 18:14:52332 GetAlternateProtocolFromParam() + "\r\n";
[email protected]8a0fc822013-06-27 20:52:43333 }
334
[email protected]202965992011-12-07 23:04:51335 // Either |write_failure| specifies a write failure or |read_failure|
336 // specifies a read failure when using a reused socket. In either case, the
337 // failure should cause the network transaction to resend the request, and the
338 // other argument should be NULL.
339 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
340 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52341
[email protected]a34f61ee2014-03-18 20:59:49342 // Either |write_failure| specifies a write failure or |read_failure|
343 // specifies a read failure when using a reused socket. In either case, the
344 // failure should cause the network transaction to resend the request, and the
345 // other argument should be NULL.
346 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10347 const MockRead* read_failure,
348 bool use_spdy);
[email protected]a34f61ee2014-03-18 20:59:49349
[email protected]5a60c8b2011-10-19 20:14:29350 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
351 size_t data_count) {
[email protected]ff007e162009-05-23 09:13:15352 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52353
[email protected]ff007e162009-05-23 09:13:15354 HttpRequestInfo request;
355 request.method = "GET";
bncce36dca22015-04-21 22:11:23356 request.url = GURL("http://www.example.org/");
[email protected]ff007e162009-05-23 09:13:15357 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52358
vishal.b62985ca92015-04-17 08:45:51359 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07360 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:42361 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:27362 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:41363 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:27364
[email protected]5a60c8b2011-10-19 20:14:29365 for (size_t i = 0; i < data_count; ++i) {
[email protected]bb88e1d32013-05-03 23:11:07366 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
[email protected]5a60c8b2011-10-19 20:14:29367 }
initial.commit586acc5fe2008-07-26 22:42:52368
[email protected]49639fa2011-12-20 23:22:41369 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52370
eroman24bc6a12015-05-06 19:55:48371 EXPECT_TRUE(log.bound().IsCapturing());
[email protected]49639fa2011-12-20 23:22:41372 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]ff007e162009-05-23 09:13:15373 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52374
[email protected]ff007e162009-05-23 09:13:15375 out.rv = callback.WaitForResult();
sclittlefb249892015-09-10 21:33:22376 out.total_received_bytes = trans->GetTotalReceivedBytes();
377 out.total_sent_bytes = trans->GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25378
379 // Even in the failure cases that use this function, connections are always
380 // successfully established before the error.
381 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
382 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
383
[email protected]ff007e162009-05-23 09:13:15384 if (out.rv != OK)
385 return out;
386
387 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50388 // Can't use ASSERT_* inside helper functions like this, so
389 // return an error.
[email protected]90499482013-06-01 00:39:50390 if (response == NULL || response->headers.get() == NULL) {
[email protected]fe2255a2011-09-20 19:37:50391 out.rv = ERR_UNEXPECTED;
392 return out;
393 }
[email protected]ff007e162009-05-23 09:13:15394 out.status_line = response->headers->GetStatusLine();
395
[email protected]80a09a82012-11-16 17:40:06396 EXPECT_EQ("127.0.0.1", response->socket_address.host());
397 EXPECT_EQ(80, response->socket_address.port());
[email protected]6d81b482011-02-22 19:47:19398
ttuttled9dbc652015-09-29 20:00:59399 bool got_endpoint =
400 trans->GetRemoteEndpoint(&out.remote_endpoint_after_start);
401 EXPECT_EQ(got_endpoint,
402 out.remote_endpoint_after_start.address().size() > 0);
403
[email protected]ff007e162009-05-23 09:13:15404 rv = ReadTransaction(trans.get(), &out.response_data);
405 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40406
mmenke43758e62015-05-04 21:09:46407 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:40408 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39409 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40410 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12411 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39412 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40413 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39414 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
415 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15416
[email protected]f3da152d2012-06-02 01:00:57417 std::string line;
418 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
419 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
420
[email protected]79e1fd62013-06-20 06:50:04421 HttpRequestHeaders request_headers;
422 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
423 std::string value;
424 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
bncce36dca22015-04-21 22:11:23425 EXPECT_EQ("www.example.org", value);
[email protected]79e1fd62013-06-20 06:50:04426 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
427 EXPECT_EQ("keep-alive", value);
428
429 std::string response_headers;
430 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
bncce36dca22015-04-21 22:11:23431 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
[email protected]79e1fd62013-06-20 06:50:04432 response_headers);
[email protected]3deb9a52010-11-11 00:24:40433
sclittlefb249892015-09-10 21:33:22434 out.total_received_bytes = trans->GetTotalReceivedBytes();
435 // The total number of sent bytes should not have changed.
436 EXPECT_EQ(out.total_sent_bytes, trans->GetTotalSentBytes());
437
ttuttle1f2d7e92015-04-28 16:17:47438 trans->GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47439 return out;
[email protected]ff007e162009-05-23 09:13:15440 }
initial.commit586acc5fe2008-07-26 22:42:52441
[email protected]5a60c8b2011-10-19 20:14:29442 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
443 size_t reads_count) {
sclittlefb249892015-09-10 21:33:22444 MockWrite data_writes[] = {
445 MockWrite("GET / HTTP/1.1\r\n"
446 "Host: www.example.org\r\n"
447 "Connection: keep-alive\r\n\r\n"),
448 };
[email protected]5a60c8b2011-10-19 20:14:29449
sclittlefb249892015-09-10 21:33:22450 StaticSocketDataProvider reads(data_reads, reads_count, data_writes,
451 arraysize(data_writes));
452 StaticSocketDataProvider* data[] = {&reads};
453 SimpleGetHelperResult out = SimpleGetHelperForData(data, 1);
454
455 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
456 out.total_sent_bytes);
457 return out;
[email protected]b8015c42013-12-24 15:18:19458 }
459
[email protected]ff007e162009-05-23 09:13:15460 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
461 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52462
[email protected]ff007e162009-05-23 09:13:15463 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07464
465 void BypassHostCacheOnRefreshHelper(int load_flags);
466
467 void CheckErrorIsPassedBack(int error, IoMode mode);
468
[email protected]4bd46222013-05-14 19:32:23469 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07470 SpdySessionDependencies session_deps_;
[email protected]483fa202013-05-14 01:07:03471
472 // Original socket limits. Some tests set these. Safest to always restore
473 // them once each test has been run.
474 int old_max_group_sockets_;
475 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15476};
[email protected]231d5a32008-09-13 00:45:27477
rdsmithebb50aa2015-11-12 03:44:38478INSTANTIATE_TEST_CASE_P(ProtoPlusDepend,
bnc57685ae62015-03-10 21:27:20479 HttpNetworkTransactionTest,
rdsmithebb50aa2015-11-12 03:44:38480 testing::Values(kTestCaseSPDY31,
481 kTestCaseHTTP2NoPriorityDependencies,
482 kTestCaseHTTP2PriorityDependencies));
[email protected]23e482282013-06-14 16:08:02483
[email protected]448d4ca52012-03-04 04:12:23484namespace {
485
[email protected]1826a402014-01-08 15:40:48486class BeforeNetworkStartHandler {
487 public:
488 explicit BeforeNetworkStartHandler(bool defer)
489 : defer_on_before_network_start_(defer),
490 observed_before_network_start_(false) {}
491
492 void OnBeforeNetworkStart(bool* defer) {
493 *defer = defer_on_before_network_start_;
494 observed_before_network_start_ = true;
495 }
496
497 bool observed_before_network_start() const {
498 return observed_before_network_start_;
499 }
500
501 private:
502 const bool defer_on_before_network_start_;
503 bool observed_before_network_start_;
504
505 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
506};
507
[email protected]597a1ab2014-06-26 08:12:27508class BeforeProxyHeadersSentHandler {
509 public:
510 BeforeProxyHeadersSentHandler()
511 : observed_before_proxy_headers_sent_(false) {}
512
[email protected]1252d42f2014-07-01 21:20:20513 void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
514 HttpRequestHeaders* request_headers) {
[email protected]597a1ab2014-06-26 08:12:27515 observed_before_proxy_headers_sent_ = true;
516 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
517 }
518
519 bool observed_before_proxy_headers_sent() const {
520 return observed_before_proxy_headers_sent_;
521 }
522
523 std::string observed_proxy_server_uri() const {
524 return observed_proxy_server_uri_;
525 }
526
527 private:
528 bool observed_before_proxy_headers_sent_;
529 std::string observed_proxy_server_uri_;
530
531 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler);
532};
533
[email protected]15a5ccf82008-10-23 19:57:43534// Fill |str| with a long header list that consumes >= |size| bytes.
535void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51536 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19537 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
538 const int sizeof_row = strlen(row);
539 const int num_rows = static_cast<int>(
540 ceil(static_cast<float>(size) / sizeof_row));
541 const int sizeof_data = num_rows * sizeof_row;
542 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43543 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51544
[email protected]4ddaf2502008-10-23 18:26:19545 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43546 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19547}
548
thakis84dff942015-07-28 20:47:38549#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29550// Alternative functions that eliminate randomness and dependency on the local
551// host name so that the generated NTLM messages are reproducible.
avibf0746c2015-12-09 19:53:14552void MockGenerateRandom1(uint8_t* output, size_t n) {
553 static const uint8_t bytes[] = {0x55, 0x29, 0x66, 0x26,
554 0x6b, 0x9c, 0x73, 0x54};
[email protected]385a4672009-03-11 22:21:29555 static size_t current_byte = 0;
556 for (size_t i = 0; i < n; ++i) {
557 output[i] = bytes[current_byte++];
558 current_byte %= arraysize(bytes);
559 }
560}
561
avibf0746c2015-12-09 19:53:14562void MockGenerateRandom2(uint8_t* output, size_t n) {
563 static const uint8_t bytes[] = {0x96, 0x79, 0x85, 0xe7, 0x49, 0x93,
564 0x70, 0xa1, 0x4e, 0xe7, 0x87, 0x45,
565 0x31, 0x5b, 0xd3, 0x1f};
[email protected]385a4672009-03-11 22:21:29566 static size_t current_byte = 0;
567 for (size_t i = 0; i < n; ++i) {
568 output[i] = bytes[current_byte++];
569 current_byte %= arraysize(bytes);
570 }
571}
572
[email protected]fe2bc6a2009-03-23 16:52:20573std::string MockGetHostName() {
574 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29575}
thakis84dff942015-07-28 20:47:38576#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29577
[email protected]e60e47a2010-07-14 03:37:18578template<typename ParentPool>
579class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31580 public:
[email protected]9e1bdd32011-02-03 21:48:34581 CaptureGroupNameSocketPool(HostResolver* host_resolver,
582 CertVerifier* cert_verifier);
[email protected]e60e47a2010-07-14 03:37:18583
[email protected]d80a4322009-08-14 07:07:49584 const std::string last_group_name_received() const {
585 return last_group_name_;
586 }
587
dmichaeld6e570d2014-12-18 22:30:57588 int RequestSocket(const std::string& group_name,
589 const void* socket_params,
590 RequestPriority priority,
mmenked3641e12016-01-28 16:06:15591 ClientSocketPool::RespectLimits respect_limits,
dmichaeld6e570d2014-12-18 22:30:57592 ClientSocketHandle* handle,
593 const CompletionCallback& callback,
594 const BoundNetLog& net_log) override {
[email protected]04e5be32009-06-26 20:00:31595 last_group_name_ = group_name;
596 return ERR_IO_PENDING;
597 }
dmichaeld6e570d2014-12-18 22:30:57598 void CancelRequest(const std::string& group_name,
599 ClientSocketHandle* handle) override {}
600 void ReleaseSocket(const std::string& group_name,
601 scoped_ptr<StreamSocket> socket,
602 int id) override {}
603 void CloseIdleSockets() override {}
604 int IdleSocketCount() const override { return 0; }
605 int IdleSocketCountInGroup(const std::string& group_name) const override {
[email protected]04e5be32009-06-26 20:00:31606 return 0;
607 }
dmichaeld6e570d2014-12-18 22:30:57608 LoadState GetLoadState(const std::string& group_name,
609 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31610 return LOAD_STATE_IDLE;
611 }
dmichaeld6e570d2014-12-18 22:30:57612 base::TimeDelta ConnectionTimeout() const override {
[email protected]a796bcec2010-03-22 17:17:26613 return base::TimeDelta();
614 }
[email protected]d80a4322009-08-14 07:07:49615
616 private:
[email protected]04e5be32009-06-26 20:00:31617 std::string last_group_name_;
618};
619
[email protected]ab739042011-04-07 15:22:28620typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
621CaptureGroupNameTransportSocketPool;
[email protected]e772db3f2010-07-12 18:11:13622typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
623CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06624typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11625CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18626typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
627CaptureGroupNameSSLSocketPool;
628
rkaplowd90695c2015-03-25 22:12:41629template <typename ParentPool>
[email protected]e60e47a2010-07-14 03:37:18630CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34631 HostResolver* host_resolver,
632 CertVerifier* /* cert_verifier */)
rkaplowd90695c2015-03-25 22:12:41633 : ParentPool(0, 0, host_resolver, NULL, NULL) {
634}
[email protected]e60e47a2010-07-14 03:37:18635
hashimoto0d3e4fb2015-01-09 05:02:50636template <>
[email protected]2df19bb2010-08-25 20:13:46637CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
hashimotodae13b02015-01-15 04:28:21638 HostResolver* /* host_resolver */,
[email protected]9e1bdd32011-02-03 21:48:34639 CertVerifier* /* cert_verifier */)
rkaplowd90695c2015-03-25 22:12:41640 : HttpProxyClientSocketPool(0, 0, NULL, NULL, NULL) {
hashimoto0d3e4fb2015-01-09 05:02:50641}
[email protected]2df19bb2010-08-25 20:13:46642
[email protected]007b3f82013-04-09 08:46:45643template <>
[email protected]e60e47a2010-07-14 03:37:18644CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
hashimotodae13b02015-01-15 04:28:21645 HostResolver* /* host_resolver */,
[email protected]9e1bdd32011-02-03 21:48:34646 CertVerifier* cert_verifier)
[email protected]007b3f82013-04-09 08:46:45647 : SSLClientSocketPool(0,
648 0,
[email protected]007b3f82013-04-09 08:46:45649 cert_verifier,
650 NULL,
651 NULL,
[email protected]284303b62013-11-28 15:11:54652 NULL,
eranm6571b2b2014-12-03 15:53:23653 NULL,
[email protected]007b3f82013-04-09 08:46:45654 std::string(),
655 NULL,
656 NULL,
657 NULL,
658 NULL,
659 NULL,
[email protected]8e458552014-08-05 00:02:15660 NULL) {
661}
[email protected]2227c692010-05-04 15:36:11662
[email protected]231d5a32008-09-13 00:45:27663//-----------------------------------------------------------------------------
664
[email protected]79cb5c12011-09-12 13:12:04665// Helper functions for validating that AuthChallengeInfo's are correctly
666// configured for common cases.
667bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
668 if (!auth_challenge)
669 return false;
670 EXPECT_FALSE(auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:23671 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:04672 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19673 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04674 return true;
675}
676
677bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
678 if (!auth_challenge)
679 return false;
680 EXPECT_TRUE(auth_challenge->is_proxy);
681 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
682 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19683 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04684 return true;
685}
686
687bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
688 if (!auth_challenge)
689 return false;
690 EXPECT_FALSE(auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:23691 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:04692 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19693 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04694 return true;
695}
696
thakis84dff942015-07-28 20:47:38697#if defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04698bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
699 if (!auth_challenge)
700 return false;
701 EXPECT_FALSE(auth_challenge->is_proxy);
702 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
703 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19704 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04705 return true;
706}
thakis84dff942015-07-28 20:47:38707#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04708
[email protected]448d4ca52012-03-04 04:12:23709} // namespace
710
[email protected]23e482282013-06-14 16:08:02711TEST_P(HttpNetworkTransactionTest, Basic) {
mmenkee65e7af2015-10-13 17:16:42712 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:40713 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:41714 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]231d5a32008-09-13 00:45:27715}
716
[email protected]23e482282013-06-14 16:08:02717TEST_P(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27718 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35719 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
720 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06721 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27722 };
[email protected]31a2bfe2010-02-09 08:03:39723 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
724 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42725 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27726 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
727 EXPECT_EQ("hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22728 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
729 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47730 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59731
732 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27733}
734
735// Response with no status line.
[email protected]23e482282013-06-14 16:08:02736TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27737 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35738 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06739 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27740 };
[email protected]31a2bfe2010-02-09 08:03:39741 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
742 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42743 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27744 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
745 EXPECT_EQ("hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22746 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
747 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27748}
749
750// Allow up to 4 bytes of junk to precede status line.
[email protected]23e482282013-06-14 16:08:02751TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27752 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35753 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06754 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27755 };
[email protected]31a2bfe2010-02-09 08:03:39756 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
757 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42758 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27759 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
760 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22761 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
762 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27763}
764
765// Allow up to 4 bytes of junk to precede status line.
[email protected]23e482282013-06-14 16:08:02766TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27767 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35768 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06769 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27770 };
[email protected]31a2bfe2010-02-09 08:03:39771 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
772 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42773 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27774 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
775 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22776 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
777 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27778}
779
780// Beyond 4 bytes of slop and it should fail to find a status line.
[email protected]23e482282013-06-14 16:08:02781TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27782 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35783 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06784 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27785 };
[email protected]31a2bfe2010-02-09 08:03:39786 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
787 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42788 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25789 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
790 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
sclittlefb249892015-09-10 21:33:22791 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
792 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27793}
794
795// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
[email protected]23e482282013-06-14 16:08:02796TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27797 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35798 MockRead("\n"),
799 MockRead("\n"),
800 MockRead("Q"),
801 MockRead("J"),
802 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06803 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27804 };
[email protected]31a2bfe2010-02-09 08:03:39805 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
806 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42807 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27808 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
809 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22810 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
811 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27812}
813
814// Close the connection before enough bytes to have a status line.
[email protected]23e482282013-06-14 16:08:02815TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27816 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35817 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06818 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27819 };
[email protected]31a2bfe2010-02-09 08:03:39820 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
821 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42822 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27823 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
824 EXPECT_EQ("HTT", out.response_data);
sclittlefb249892015-09-10 21:33:22825 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
826 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:52827}
828
[email protected]f9d44aa2008-09-23 23:57:17829// Simulate a 204 response, lacking a Content-Length header, sent over a
830// persistent connection. The response should still terminate since a 204
831// cannot have a response body.
[email protected]23e482282013-06-14 16:08:02832TEST_P(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:19833 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:17834 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35835 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:19836 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:06837 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:17838 };
[email protected]31a2bfe2010-02-09 08:03:39839 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
840 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42841 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17842 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
843 EXPECT_EQ("", out.response_data);
sclittlefb249892015-09-10 21:33:22844 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
845 int64_t response_size = reads_size - strlen(junk);
846 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:17847}
848
[email protected]0877e3d2009-10-17 22:29:57849// A simple request using chunked encoding with some extra data after.
[email protected]23e482282013-06-14 16:08:02850TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:19851 std::string final_chunk = "0\r\n\r\n";
852 std::string extra_data = "HTTP/1.1 200 OK\r\n";
853 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:57854 MockRead data_reads[] = {
855 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
856 MockRead("5\r\nHello\r\n"),
857 MockRead("1\r\n"),
858 MockRead(" \r\n"),
859 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:19860 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:06861 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:57862 };
[email protected]31a2bfe2010-02-09 08:03:39863 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
864 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57865 EXPECT_EQ(OK, out.rv);
866 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
867 EXPECT_EQ("Hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22868 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
869 int64_t response_size = reads_size - extra_data.size();
870 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:57871}
872
[email protected]9fe44f52010-09-23 18:36:00873// Next tests deal with http://crbug.com/56344.
874
[email protected]23e482282013-06-14 16:08:02875TEST_P(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00876 MultipleContentLengthHeadersNoTransferEncoding) {
877 MockRead data_reads[] = {
878 MockRead("HTTP/1.1 200 OK\r\n"),
879 MockRead("Content-Length: 10\r\n"),
880 MockRead("Content-Length: 5\r\n\r\n"),
881 };
882 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
883 arraysize(data_reads));
884 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
885}
886
[email protected]23e482282013-06-14 16:08:02887TEST_P(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04888 DuplicateContentLengthHeadersNoTransferEncoding) {
889 MockRead data_reads[] = {
890 MockRead("HTTP/1.1 200 OK\r\n"),
891 MockRead("Content-Length: 5\r\n"),
892 MockRead("Content-Length: 5\r\n\r\n"),
893 MockRead("Hello"),
894 };
895 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
896 arraysize(data_reads));
897 EXPECT_EQ(OK, out.rv);
898 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
899 EXPECT_EQ("Hello", out.response_data);
900}
901
[email protected]23e482282013-06-14 16:08:02902TEST_P(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04903 ComplexContentLengthHeadersNoTransferEncoding) {
904 // More than 2 dupes.
905 {
906 MockRead data_reads[] = {
907 MockRead("HTTP/1.1 200 OK\r\n"),
908 MockRead("Content-Length: 5\r\n"),
909 MockRead("Content-Length: 5\r\n"),
910 MockRead("Content-Length: 5\r\n\r\n"),
911 MockRead("Hello"),
912 };
913 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
914 arraysize(data_reads));
915 EXPECT_EQ(OK, out.rv);
916 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
917 EXPECT_EQ("Hello", out.response_data);
918 }
919 // HTTP/1.0
920 {
921 MockRead data_reads[] = {
922 MockRead("HTTP/1.0 200 OK\r\n"),
923 MockRead("Content-Length: 5\r\n"),
924 MockRead("Content-Length: 5\r\n"),
925 MockRead("Content-Length: 5\r\n\r\n"),
926 MockRead("Hello"),
927 };
928 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
929 arraysize(data_reads));
930 EXPECT_EQ(OK, out.rv);
931 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
932 EXPECT_EQ("Hello", out.response_data);
933 }
934 // 2 dupes and one mismatched.
935 {
936 MockRead data_reads[] = {
937 MockRead("HTTP/1.1 200 OK\r\n"),
938 MockRead("Content-Length: 10\r\n"),
939 MockRead("Content-Length: 10\r\n"),
940 MockRead("Content-Length: 5\r\n\r\n"),
941 };
942 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
943 arraysize(data_reads));
944 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
945 }
946}
947
[email protected]23e482282013-06-14 16:08:02948TEST_P(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00949 MultipleContentLengthHeadersTransferEncoding) {
950 MockRead data_reads[] = {
951 MockRead("HTTP/1.1 200 OK\r\n"),
952 MockRead("Content-Length: 666\r\n"),
953 MockRead("Content-Length: 1337\r\n"),
954 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
955 MockRead("5\r\nHello\r\n"),
956 MockRead("1\r\n"),
957 MockRead(" \r\n"),
958 MockRead("5\r\nworld\r\n"),
959 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:06960 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:00961 };
962 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
963 arraysize(data_reads));
964 EXPECT_EQ(OK, out.rv);
965 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
966 EXPECT_EQ("Hello world", out.response_data);
967}
968
[email protected]1628fe92011-10-04 23:04:55969// Next tests deal with http://crbug.com/98895.
970
971// Checks that a single Content-Disposition header results in no error.
[email protected]23e482282013-06-14 16:08:02972TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:55973 MockRead data_reads[] = {
974 MockRead("HTTP/1.1 200 OK\r\n"),
975 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
976 MockRead("Content-Length: 5\r\n\r\n"),
977 MockRead("Hello"),
978 };
979 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
980 arraysize(data_reads));
981 EXPECT_EQ(OK, out.rv);
982 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
983 EXPECT_EQ("Hello", out.response_data);
984}
985
[email protected]54a9c6e52012-03-21 20:10:59986// Checks that two identical Content-Disposition headers result in no error.
[email protected]23e482282013-06-14 16:08:02987TEST_P(HttpNetworkTransactionTest,
[email protected]54a9c6e52012-03-21 20:10:59988 TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:55989 MockRead data_reads[] = {
990 MockRead("HTTP/1.1 200 OK\r\n"),
991 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
992 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
993 MockRead("Content-Length: 5\r\n\r\n"),
994 MockRead("Hello"),
995 };
996 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
997 arraysize(data_reads));
[email protected]54a9c6e52012-03-21 20:10:59998 EXPECT_EQ(OK, out.rv);
999 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1000 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551001}
1002
1003// Checks that two distinct Content-Disposition headers result in an error.
[email protected]23e482282013-06-14 16:08:021004TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551005 MockRead data_reads[] = {
1006 MockRead("HTTP/1.1 200 OK\r\n"),
1007 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1008 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1009 MockRead("Content-Length: 5\r\n\r\n"),
1010 MockRead("Hello"),
1011 };
1012 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1013 arraysize(data_reads));
1014 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
1015}
1016
[email protected]54a9c6e52012-03-21 20:10:591017// Checks that two identical Location headers result in no error.
1018// Also tests Location header behavior.
[email protected]23e482282013-06-14 16:08:021019TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551020 MockRead data_reads[] = {
1021 MockRead("HTTP/1.1 302 Redirect\r\n"),
1022 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591023 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551024 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061025 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551026 };
1027
1028 HttpRequestInfo request;
1029 request.method = "GET";
1030 request.url = GURL("http://redirect.com/");
1031 request.load_flags = 0;
1032
mmenkee65e7af2015-10-13 17:16:421033 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1628fe92011-10-04 23:04:551034 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411035 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]1628fe92011-10-04 23:04:551036
1037 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071038 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551039
[email protected]49639fa2011-12-20 23:22:411040 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551041
[email protected]49639fa2011-12-20 23:22:411042 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1628fe92011-10-04 23:04:551043 EXPECT_EQ(ERR_IO_PENDING, rv);
1044
1045 EXPECT_EQ(OK, callback.WaitForResult());
1046
1047 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501048 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
[email protected]1628fe92011-10-04 23:04:551049 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1050 std::string url;
1051 EXPECT_TRUE(response->headers->IsRedirect(&url));
1052 EXPECT_EQ("http://good.com/", url);
[email protected]d8fc4722014-06-13 13:17:151053 EXPECT_TRUE(response->proxy_server.IsEmpty());
[email protected]1628fe92011-10-04 23:04:551054}
1055
[email protected]1628fe92011-10-04 23:04:551056// Checks that two distinct Location headers result in an error.
[email protected]23e482282013-06-14 16:08:021057TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551058 MockRead data_reads[] = {
1059 MockRead("HTTP/1.1 302 Redirect\r\n"),
1060 MockRead("Location: http://good.com/\r\n"),
1061 MockRead("Location: http://evil.com/\r\n"),
1062 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061063 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551064 };
1065 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1066 arraysize(data_reads));
1067 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
1068}
1069
[email protected]ef0faf2e72009-03-05 23:27:231070// Do a request using the HEAD method. Verify that we don't try to read the
1071// message body (since HEAD has none).
[email protected]23e482282013-06-14 16:08:021072TEST_P(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421073 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231074 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231075 request.url = GURL("http://www.example.org/");
[email protected]ef0faf2e72009-03-05 23:27:231076 request.load_flags = 0;
1077
mmenkee65e7af2015-10-13 17:16:421078 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271079 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411080 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]597a1ab2014-06-26 08:12:271081 BeforeProxyHeadersSentHandler proxy_headers_handler;
1082 trans->SetBeforeProxyHeadersSentCallback(
1083 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
1084 base::Unretained(&proxy_headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271085
[email protected]ef0faf2e72009-03-05 23:27:231086 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131087 MockWrite("HEAD / HTTP/1.1\r\n"
1088 "Host: www.example.org\r\n"
1089 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231090 };
1091 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231092 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1093 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231094
mmenked39192ee2015-12-09 00:57:231095 // No response body because the test stops reading here.
1096 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231097 };
1098
[email protected]31a2bfe2010-02-09 08:03:391099 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1100 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:071101 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231102
[email protected]49639fa2011-12-20 23:22:411103 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231104
[email protected]49639fa2011-12-20 23:22:411105 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421106 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:231107
1108 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421109 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:231110
[email protected]1c773ea12009-04-28 19:58:421111 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501112 ASSERT_TRUE(response != NULL);
[email protected]ef0faf2e72009-03-05 23:27:231113
1114 // Check that the headers got parsed.
[email protected]90499482013-06-01 00:39:501115 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]ef0faf2e72009-03-05 23:27:231116 EXPECT_EQ(1234, response->headers->GetContentLength());
1117 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151118 EXPECT_TRUE(response->proxy_server.IsEmpty());
[email protected]597a1ab2014-06-26 08:12:271119 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
[email protected]ef0faf2e72009-03-05 23:27:231120
1121 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101122 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231123 bool has_server_header = response->headers->EnumerateHeader(
1124 &iter, "Server", &server_header);
1125 EXPECT_TRUE(has_server_header);
1126 EXPECT_EQ("Blah", server_header);
1127
1128 // Reading should give EOF right away, since there is no message body
1129 // (despite non-zero content-length).
1130 std::string response_data;
1131 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421132 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:231133 EXPECT_EQ("", response_data);
1134}
1135
[email protected]23e482282013-06-14 16:08:021136TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
mmenkee65e7af2015-10-13 17:16:421137 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521138
1139 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351140 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1141 MockRead("hello"),
1142 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1143 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061144 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521145 };
[email protected]31a2bfe2010-02-09 08:03:391146 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071147 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521148
[email protected]0b0bf032010-09-21 18:08:501149 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521150 "hello", "world"
1151 };
1152
1153 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421154 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521155 request.method = "GET";
bncce36dca22015-04-21 22:11:231156 request.url = GURL("http://www.example.org/");
initial.commit586acc5fe2008-07-26 22:42:521157 request.load_flags = 0;
1158
[email protected]262eec82013-03-19 21:01:361159 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501160 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271161
[email protected]49639fa2011-12-20 23:22:411162 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521163
[email protected]49639fa2011-12-20 23:22:411164 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421165 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521166
1167 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421168 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521169
[email protected]1c773ea12009-04-28 19:58:421170 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501171 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521172
[email protected]90499482013-06-01 00:39:501173 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251174 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151175 EXPECT_TRUE(response->proxy_server.IsEmpty());
initial.commit586acc5fe2008-07-26 22:42:521176
1177 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571178 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421179 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251180 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521181 }
1182}
1183
[email protected]23e482282013-06-14 16:08:021184TEST_P(HttpNetworkTransactionTest, Ignores100) {
olli.raula6df48b2a2015-11-26 07:40:221185 std::vector<scoped_ptr<UploadElementReader>> element_readers;
1186 element_readers.push_back(
1187 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
1188 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271189
[email protected]1c773ea12009-04-28 19:58:421190 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521191 request.method = "POST";
1192 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271193 request.upload_data_stream = &upload_data_stream;
initial.commit586acc5fe2008-07-26 22:42:521194 request.load_flags = 0;
1195
mmenkee65e7af2015-10-13 17:16:421196 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271197 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411198 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271199
initial.commit586acc5fe2008-07-26 22:42:521200 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351201 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1202 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1203 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061204 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521205 };
[email protected]31a2bfe2010-02-09 08:03:391206 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071207 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521208
[email protected]49639fa2011-12-20 23:22:411209 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521210
[email protected]49639fa2011-12-20 23:22:411211 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421212 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521213
1214 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421215 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521216
[email protected]1c773ea12009-04-28 19:58:421217 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501218 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521219
[email protected]90499482013-06-01 00:39:501220 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251221 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521222
1223 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571224 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421225 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251226 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521227}
1228
[email protected]3a2d3662009-03-27 03:49:141229// This test is almost the same as Ignores100 above, but the response contains
1230// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571231// HTTP/1.1 and the two status headers are read in one read.
[email protected]23e482282013-06-14 16:08:021232TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421233 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141234 request.method = "GET";
1235 request.url = GURL("http://www.foo.com/");
1236 request.load_flags = 0;
1237
mmenkee65e7af2015-10-13 17:16:421238 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271239 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411240 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271241
[email protected]3a2d3662009-03-27 03:49:141242 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571243 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1244 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141245 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061246 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141247 };
[email protected]31a2bfe2010-02-09 08:03:391248 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071249 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141250
[email protected]49639fa2011-12-20 23:22:411251 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141252
[email protected]49639fa2011-12-20 23:22:411253 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421254 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:141255
1256 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421257 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:141258
[email protected]1c773ea12009-04-28 19:58:421259 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501260 ASSERT_TRUE(response != NULL);
[email protected]3a2d3662009-03-27 03:49:141261
[email protected]90499482013-06-01 00:39:501262 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3a2d3662009-03-27 03:49:141263 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1264
1265 std::string response_data;
1266 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421267 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:141268 EXPECT_EQ("hello world", response_data);
1269}
1270
[email protected]23e482282013-06-14 16:08:021271TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081272 HttpRequestInfo request;
1273 request.method = "POST";
1274 request.url = GURL("http://www.foo.com/");
1275 request.load_flags = 0;
1276
mmenkee65e7af2015-10-13 17:16:421277 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
zmo9528c9f42015-08-04 22:12:081278 scoped_ptr<HttpTransaction> trans(
1279 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1280
1281 MockRead data_reads[] = {
1282 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1283 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381284 };
zmo9528c9f42015-08-04 22:12:081285 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1286 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381287
zmo9528c9f42015-08-04 22:12:081288 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381289
zmo9528c9f42015-08-04 22:12:081290 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1291 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ee9410e72010-01-07 01:42:381292
zmo9528c9f42015-08-04 22:12:081293 rv = callback.WaitForResult();
1294 EXPECT_EQ(OK, rv);
[email protected]ee9410e72010-01-07 01:42:381295
zmo9528c9f42015-08-04 22:12:081296 std::string response_data;
1297 rv = ReadTransaction(trans.get(), &response_data);
1298 EXPECT_EQ(OK, rv);
1299 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381300}
1301
[email protected]23e482282013-06-14 16:08:021302TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381303 HttpRequestInfo request;
1304 request.method = "POST";
1305 request.url = GURL("http://www.foo.com/");
1306 request.load_flags = 0;
1307
mmenkee65e7af2015-10-13 17:16:421308 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271309 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411310 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271311
[email protected]ee9410e72010-01-07 01:42:381312 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061313 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381314 };
[email protected]31a2bfe2010-02-09 08:03:391315 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071316 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381317
[email protected]49639fa2011-12-20 23:22:411318 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381319
[email protected]49639fa2011-12-20 23:22:411320 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:381321 EXPECT_EQ(ERR_IO_PENDING, rv);
1322
1323 rv = callback.WaitForResult();
1324 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1325}
1326
[email protected]23e482282013-06-14 16:08:021327void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511328 const MockWrite* write_failure,
1329 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421330 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521331 request.method = "GET";
1332 request.url = GURL("http://www.foo.com/");
1333 request.load_flags = 0;
1334
vishal.b62985ca92015-04-17 08:45:511335 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071336 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421337 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271338
[email protected]202965992011-12-07 23:04:511339 // Written data for successfully sending both requests.
1340 MockWrite data1_writes[] = {
1341 MockWrite("GET / HTTP/1.1\r\n"
1342 "Host: www.foo.com\r\n"
1343 "Connection: keep-alive\r\n\r\n"),
1344 MockWrite("GET / HTTP/1.1\r\n"
1345 "Host: www.foo.com\r\n"
1346 "Connection: keep-alive\r\n\r\n")
1347 };
1348
1349 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521350 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351351 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1352 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061353 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521354 };
[email protected]202965992011-12-07 23:04:511355
1356 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491357 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511358 data1_writes[1] = *write_failure;
1359 } else {
1360 ASSERT_TRUE(read_failure);
1361 data1_reads[2] = *read_failure;
1362 }
1363
1364 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1365 data1_writes, arraysize(data1_writes));
[email protected]bb88e1d32013-05-03 23:11:071366 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521367
1368 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351369 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1370 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061371 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521372 };
[email protected]31a2bfe2010-02-09 08:03:391373 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071374 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521375
thestig9d3bb0c2015-01-24 00:49:511376 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521377 "hello", "world"
1378 };
1379
avibf0746c2015-12-09 19:53:141380 uint32_t first_socket_log_id = NetLog::Source::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521381 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411382 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521383
[email protected]262eec82013-03-19 21:01:361384 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501385 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
initial.commit586acc5fe2008-07-26 22:42:521386
[email protected]49639fa2011-12-20 23:22:411387 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421388 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521389
1390 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421391 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521392
[email protected]58e32bb2013-01-21 18:23:251393 LoadTimingInfo load_timing_info;
1394 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1395 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1396 if (i == 0) {
1397 first_socket_log_id = load_timing_info.socket_log_id;
1398 } else {
1399 // The second request should be using a new socket.
1400 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1401 }
1402
[email protected]1c773ea12009-04-28 19:58:421403 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501404 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521405
[email protected]90499482013-06-01 00:39:501406 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251407 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521408
1409 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571410 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421411 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251412 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521413 }
1414}
[email protected]3d2a59b2008-09-26 19:44:251415
[email protected]a34f61ee2014-03-18 20:59:491416void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1417 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101418 const MockRead* read_failure,
1419 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491420 HttpRequestInfo request;
1421 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101422 request.url = GURL("https://www.foo.com/");
[email protected]a34f61ee2014-03-18 20:59:491423 request.load_flags = 0;
1424
vishal.b62985ca92015-04-17 08:45:511425 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491426 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421427 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491428
[email protected]09356c652014-03-25 15:36:101429 SSLSocketDataProvider ssl1(ASYNC, OK);
1430 SSLSocketDataProvider ssl2(ASYNC, OK);
1431 if (use_spdy) {
rdsmithebb50aa2015-11-12 03:44:381432 ssl1.SetNextProto(GetProtocol());
1433 ssl2.SetNextProto(GetProtocol());
[email protected]09356c652014-03-25 15:36:101434 }
1435 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1436 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491437
[email protected]09356c652014-03-25 15:36:101438 // SPDY versions of the request and response.
1439 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1440 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1441 scoped_ptr<SpdyFrame> spdy_response(
1442 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1443 scoped_ptr<SpdyFrame> spdy_data(
1444 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
[email protected]a34f61ee2014-03-18 20:59:491445
[email protected]09356c652014-03-25 15:36:101446 // HTTP/1.1 versions of the request and response.
1447 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1448 "Host: www.foo.com\r\n"
1449 "Connection: keep-alive\r\n\r\n";
1450 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1451 const char kHttpData[] = "hello";
1452
1453 std::vector<MockRead> data1_reads;
1454 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491455 if (write_failure) {
1456 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101457 data1_writes.push_back(*write_failure);
1458 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491459 } else {
1460 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101461 if (use_spdy) {
1462 data1_writes.push_back(CreateMockWrite(*spdy_request));
1463 } else {
1464 data1_writes.push_back(MockWrite(kHttpRequest));
1465 }
1466 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491467 }
1468
[email protected]09356c652014-03-25 15:36:101469 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1470 &data1_writes[0], data1_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491471 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1472
[email protected]09356c652014-03-25 15:36:101473 std::vector<MockRead> data2_reads;
1474 std::vector<MockWrite> data2_writes;
1475
1476 if (use_spdy) {
1477 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1478
1479 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1480 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1481 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1482 } else {
1483 data2_writes.push_back(
1484 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1485
1486 data2_reads.push_back(
1487 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1488 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1489 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1490 }
rch8e6c6c42015-05-01 14:05:131491 SequencedSocketData data2(&data2_reads[0], data2_reads.size(),
1492 &data2_writes[0], data2_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491493 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1494
1495 // Preconnect a socket.
ttuttle859dc7a2015-04-23 19:42:291496 SSLConfig ssl_config;
[email protected]a34f61ee2014-03-18 20:59:491497 session->ssl_config_service()->GetSSLConfig(&ssl_config);
bnc1f295372015-10-21 23:24:221498 session->GetAlpnProtos(&ssl_config.alpn_protos);
1499 session->GetNpnProtos(&ssl_config.npn_protos);
mmenked1205bd2015-07-15 22:26:351500 session->http_stream_factory()->PreconnectStreams(1, request, ssl_config,
1501 ssl_config);
[email protected]a34f61ee2014-03-18 20:59:491502 // Wait for the preconnect to complete.
1503 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1504 base::RunLoop().RunUntilIdle();
[email protected]09356c652014-03-25 15:36:101505 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491506
1507 // Make the request.
1508 TestCompletionCallback callback;
1509
1510 scoped_ptr<HttpTransaction> trans(
1511 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1512
1513 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1514 EXPECT_EQ(ERR_IO_PENDING, rv);
1515
1516 rv = callback.WaitForResult();
1517 EXPECT_EQ(OK, rv);
1518
1519 LoadTimingInfo load_timing_info;
1520 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101521 TestLoadTimingNotReused(
1522 load_timing_info,
1523 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491524
1525 const HttpResponseInfo* response = trans->GetResponseInfo();
1526 ASSERT_TRUE(response != NULL);
1527
1528 EXPECT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:021529 if (response->was_fetched_via_spdy) {
1530 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1531 } else {
1532 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1533 }
[email protected]a34f61ee2014-03-18 20:59:491534
1535 std::string response_data;
1536 rv = ReadTransaction(trans.get(), &response_data);
1537 EXPECT_EQ(OK, rv);
[email protected]09356c652014-03-25 15:36:101538 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491539}
1540
[email protected]23e482282013-06-14 16:08:021541TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:231542 KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061543 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]202965992011-12-07 23:04:511544 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1545}
1546
[email protected]23e482282013-06-14 16:08:021547TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061548 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]202965992011-12-07 23:04:511549 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251550}
1551
[email protected]23e482282013-06-14 16:08:021552TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061553 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]202965992011-12-07 23:04:511554 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251555}
1556
[email protected]d58ceea82014-06-04 10:55:541557// Make sure that on a 408 response (Request Timeout), the request is retried,
1558// if the socket was a reused keep alive socket.
1559TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1560 MockRead read_failure(SYNCHRONOUS,
1561 "HTTP/1.1 408 Request Timeout\r\n"
1562 "Connection: Keep-Alive\r\n"
1563 "Content-Length: 6\r\n\r\n"
1564 "Pickle");
1565 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1566}
1567
[email protected]a34f61ee2014-03-18 20:59:491568TEST_P(HttpNetworkTransactionTest,
1569 PreconnectErrorNotConnectedOnWrite) {
1570 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]09356c652014-03-25 15:36:101571 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
[email protected]a34f61ee2014-03-18 20:59:491572}
1573
1574TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1575 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]09356c652014-03-25 15:36:101576 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491577}
1578
1579TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1580 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]09356c652014-03-25 15:36:101581 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1582}
1583
1584TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1585 MockRead read_failure(ASYNC, OK); // EOF
1586 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1587}
1588
[email protected]d58ceea82014-06-04 10:55:541589// Make sure that on a 408 response (Request Timeout), the request is retried,
1590// if the socket was a preconnected (UNUSED_IDLE) socket.
1591TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1592 MockRead read_failure(SYNCHRONOUS,
1593 "HTTP/1.1 408 Request Timeout\r\n"
1594 "Connection: Keep-Alive\r\n"
1595 "Content-Length: 6\r\n\r\n"
1596 "Pickle");
1597 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1598 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1599}
1600
[email protected]09356c652014-03-25 15:36:101601TEST_P(HttpNetworkTransactionTest,
1602 SpdyPreconnectErrorNotConnectedOnWrite) {
1603 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1604 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1605}
1606
1607TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1608 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1609 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1610}
1611
1612TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1613 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1614 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1615}
1616
1617TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1618 MockRead read_failure(ASYNC, OK); // EOF
1619 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:491620}
1621
[email protected]23e482282013-06-14 16:08:021622TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421623 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251624 request.method = "GET";
bncce36dca22015-04-21 22:11:231625 request.url = GURL("http://www.example.org/");
[email protected]3d2a59b2008-09-26 19:44:251626 request.load_flags = 0;
1627
mmenkee65e7af2015-10-13 17:16:421628 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271629 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411630 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271631
[email protected]3d2a59b2008-09-26 19:44:251632 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061633 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:351634 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1635 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061636 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251637 };
[email protected]31a2bfe2010-02-09 08:03:391638 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071639 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:251640
[email protected]49639fa2011-12-20 23:22:411641 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:251642
[email protected]49639fa2011-12-20 23:22:411643 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421644 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:251645
1646 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421647 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
ttuttled9dbc652015-09-29 20:00:591648
1649 IPEndPoint endpoint;
1650 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
1651 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:251652}
1653
1654// What do various browsers do when the server closes a non-keepalive
1655// connection without sending any response header or body?
1656//
1657// IE7: error page
1658// Safari 3.1.2 (Windows): error page
1659// Firefox 3.0.1: blank page
1660// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:421661// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1662// Us: error page (EMPTY_RESPONSE)
[email protected]23e482282013-06-14 16:08:021663TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:251664 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061665 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:351666 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1667 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061668 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251669 };
[email protected]31a2bfe2010-02-09 08:03:391670 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1671 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:421672 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:251673}
[email protected]038e9a32008-10-08 22:40:161674
[email protected]1826a402014-01-08 15:40:481675// Test that network access can be deferred and resumed.
1676TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1677 HttpRequestInfo request;
1678 request.method = "GET";
bncce36dca22015-04-21 22:11:231679 request.url = GURL("http://www.example.org/");
[email protected]1826a402014-01-08 15:40:481680 request.load_flags = 0;
1681
mmenkee65e7af2015-10-13 17:16:421682 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1826a402014-01-08 15:40:481683 scoped_ptr<HttpTransaction> trans(
1684 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1685
1686 // Defer on OnBeforeNetworkStart.
1687 BeforeNetworkStartHandler net_start_handler(true); // defer
1688 trans->SetBeforeNetworkStartCallback(
1689 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1690 base::Unretained(&net_start_handler)));
1691
1692 MockRead data_reads[] = {
1693 MockRead("HTTP/1.0 200 OK\r\n"),
1694 MockRead("Content-Length: 5\r\n\r\n"),
1695 MockRead("hello"),
1696 MockRead(SYNCHRONOUS, 0),
1697 };
1698 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1699 session_deps_.socket_factory->AddSocketDataProvider(&data);
1700
1701 TestCompletionCallback callback;
1702
1703 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1704 EXPECT_EQ(ERR_IO_PENDING, rv);
1705 base::MessageLoop::current()->RunUntilIdle();
1706
1707 // Should have deferred for network start.
1708 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1709 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
[email protected]1826a402014-01-08 15:40:481710
1711 trans->ResumeNetworkStart();
1712 rv = callback.WaitForResult();
1713 EXPECT_EQ(OK, rv);
1714 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1715
1716 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1717 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1718 if (rv == ERR_IO_PENDING)
1719 rv = callback.WaitForResult();
1720 EXPECT_EQ(5, rv);
1721 trans.reset();
1722}
1723
1724// Test that network use can be deferred and canceled.
1725TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1726 HttpRequestInfo request;
1727 request.method = "GET";
bncce36dca22015-04-21 22:11:231728 request.url = GURL("http://www.example.org/");
[email protected]1826a402014-01-08 15:40:481729 request.load_flags = 0;
1730
mmenkee65e7af2015-10-13 17:16:421731 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1826a402014-01-08 15:40:481732 scoped_ptr<HttpTransaction> trans(
1733 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1734
1735 // Defer on OnBeforeNetworkStart.
1736 BeforeNetworkStartHandler net_start_handler(true); // defer
1737 trans->SetBeforeNetworkStartCallback(
1738 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1739 base::Unretained(&net_start_handler)));
1740
1741 TestCompletionCallback callback;
1742
1743 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1744 EXPECT_EQ(ERR_IO_PENDING, rv);
1745 base::MessageLoop::current()->RunUntilIdle();
1746
1747 // Should have deferred for network start.
1748 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1749 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
[email protected]1826a402014-01-08 15:40:481750}
1751
[email protected]7a5378b2012-11-04 03:25:171752// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1753// tests. There was a bug causing HttpNetworkTransaction to hang in the
1754// destructor in such situations.
1755// See http://crbug.com/154712 and http://crbug.com/156609.
[email protected]23e482282013-06-14 16:08:021756TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:171757 HttpRequestInfo request;
1758 request.method = "GET";
bncce36dca22015-04-21 22:11:231759 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171760 request.load_flags = 0;
1761
mmenkee65e7af2015-10-13 17:16:421762 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:361763 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501764 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171765
1766 MockRead data_reads[] = {
1767 MockRead("HTTP/1.0 200 OK\r\n"),
1768 MockRead("Connection: keep-alive\r\n"),
1769 MockRead("Content-Length: 100\r\n\r\n"),
1770 MockRead("hello"),
1771 MockRead(SYNCHRONOUS, 0),
1772 };
1773 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071774 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171775
1776 TestCompletionCallback callback;
1777
1778 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1779 EXPECT_EQ(ERR_IO_PENDING, rv);
1780
1781 rv = callback.WaitForResult();
1782 EXPECT_EQ(OK, rv);
1783
1784 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501785 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171786 if (rv == ERR_IO_PENDING)
1787 rv = callback.WaitForResult();
1788 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:501789 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171790 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1791
1792 trans.reset();
[email protected]2da659e2013-05-23 20:51:341793 base::MessageLoop::current()->RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171794 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1795}
1796
[email protected]23e482282013-06-14 16:08:021797TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:171798 HttpRequestInfo request;
1799 request.method = "GET";
bncce36dca22015-04-21 22:11:231800 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171801 request.load_flags = 0;
1802
mmenkee65e7af2015-10-13 17:16:421803 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:361804 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501805 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171806
1807 MockRead data_reads[] = {
1808 MockRead("HTTP/1.0 200 OK\r\n"),
1809 MockRead("Connection: keep-alive\r\n"),
1810 MockRead("Content-Length: 100\r\n\r\n"),
1811 MockRead(SYNCHRONOUS, 0),
1812 };
1813 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071814 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171815
1816 TestCompletionCallback callback;
1817
1818 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1819 EXPECT_EQ(ERR_IO_PENDING, rv);
1820
1821 rv = callback.WaitForResult();
1822 EXPECT_EQ(OK, rv);
1823
1824 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501825 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171826 if (rv == ERR_IO_PENDING)
1827 rv = callback.WaitForResult();
1828 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1829
1830 trans.reset();
[email protected]2da659e2013-05-23 20:51:341831 base::MessageLoop::current()->RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171832 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1833}
1834
[email protected]0b0bf032010-09-21 18:08:501835// Test that we correctly reuse a keep-alive connection after not explicitly
1836// reading the body.
[email protected]23e482282013-06-14 16:08:021837TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:131838 HttpRequestInfo request;
1839 request.method = "GET";
1840 request.url = GURL("http://www.foo.com/");
1841 request.load_flags = 0;
1842
vishal.b62985ca92015-04-17 08:45:511843 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071844 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421845 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271846
mmenkecc2298e2015-12-07 18:20:181847 const char* request_data =
1848 "GET / HTTP/1.1\r\n"
1849 "Host: www.foo.com\r\n"
1850 "Connection: keep-alive\r\n\r\n";
1851 MockWrite data_writes[] = {
1852 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
1853 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
1854 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
1855 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
1856 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
1857 };
1858
[email protected]0b0bf032010-09-21 18:08:501859 // Note that because all these reads happen in the same
1860 // StaticSocketDataProvider, it shows that the same socket is being reused for
1861 // all transactions.
mmenkecc2298e2015-12-07 18:20:181862 MockRead data_reads[] = {
1863 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
1864 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
1865 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
1866 MockRead(ASYNC, 7,
1867 "HTTP/1.1 302 Found\r\n"
1868 "Content-Length: 0\r\n\r\n"),
1869 MockRead(ASYNC, 9,
1870 "HTTP/1.1 302 Found\r\n"
1871 "Content-Length: 5\r\n\r\n"
1872 "hello"),
1873 MockRead(ASYNC, 11,
1874 "HTTP/1.1 301 Moved Permanently\r\n"
1875 "Content-Length: 0\r\n\r\n"),
1876 MockRead(ASYNC, 13,
1877 "HTTP/1.1 301 Moved Permanently\r\n"
1878 "Content-Length: 5\r\n\r\n"
1879 "hello"),
[email protected]fc31d6a42010-06-24 18:05:131880
mmenkecc2298e2015-12-07 18:20:181881 // In the next two rounds, IsConnectedAndIdle returns false, due to
1882 // the set_busy_before_sync_reads(true) call, while the
1883 // HttpNetworkTransaction is being shut down, but the socket is still
1884 // reuseable. See http://crbug.com/544255.
1885 MockRead(ASYNC, 15,
1886 "HTTP/1.1 200 Hunky-Dory\r\n"
1887 "Content-Length: 5\r\n\r\n"),
1888 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:131889
mmenkecc2298e2015-12-07 18:20:181890 MockRead(ASYNC, 18,
1891 "HTTP/1.1 200 Hunky-Dory\r\n"
1892 "Content-Length: 5\r\n\r\n"
1893 "he"),
1894 MockRead(SYNCHRONOUS, 19, "llo"),
1895
1896 // The body of the final request is actually read.
1897 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1898 MockRead(ASYNC, 22, "hello"),
1899 };
1900 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
1901 arraysize(data_writes));
1902 data.set_busy_before_sync_reads(true);
1903 session_deps_.socket_factory->AddSocketDataProvider(&data);
1904
1905 const int kNumUnreadBodies = arraysize(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:501906 std::string response_lines[kNumUnreadBodies];
1907
avibf0746c2015-12-09 19:53:141908 uint32_t first_socket_log_id = NetLog::Source::kInvalidId;
mmenkecc2298e2015-12-07 18:20:181909 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:411910 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:131911
[email protected]262eec82013-03-19 21:01:361912 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501913 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]fc31d6a42010-06-24 18:05:131914
[email protected]49639fa2011-12-20 23:22:411915 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
mmenkecc2298e2015-12-07 18:20:181916 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]fc31d6a42010-06-24 18:05:131917
[email protected]58e32bb2013-01-21 18:23:251918 LoadTimingInfo load_timing_info;
1919 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1920 if (i == 0) {
1921 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1922 first_socket_log_id = load_timing_info.socket_log_id;
1923 } else {
1924 TestLoadTimingReused(load_timing_info);
1925 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1926 }
1927
[email protected]fc31d6a42010-06-24 18:05:131928 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:181929 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:131930
mmenkecc2298e2015-12-07 18:20:181931 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:501932 response_lines[i] = response->headers->GetStatusLine();
1933
mmenkecc2298e2015-12-07 18:20:181934 // Delete the transaction without reading the response bodies. Then spin
1935 // the message loop, so the response bodies are drained.
1936 trans.reset();
1937 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:131938 }
[email protected]0b0bf032010-09-21 18:08:501939
1940 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:181941 "HTTP/1.1 204 No Content",
1942 "HTTP/1.1 205 Reset Content",
1943 "HTTP/1.1 304 Not Modified",
1944 "HTTP/1.1 302 Found",
1945 "HTTP/1.1 302 Found",
1946 "HTTP/1.1 301 Moved Permanently",
1947 "HTTP/1.1 301 Moved Permanently",
1948 "HTTP/1.1 200 Hunky-Dory",
1949 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:501950 };
1951
mostynb91e0da982015-01-20 19:17:271952 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1953 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:501954
1955 for (int i = 0; i < kNumUnreadBodies; ++i)
1956 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1957
[email protected]49639fa2011-12-20 23:22:411958 TestCompletionCallback callback;
[email protected]262eec82013-03-19 21:01:361959 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501960 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:411961 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
mmenkecc2298e2015-12-07 18:20:181962 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]0b0bf032010-09-21 18:08:501963 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:181964 ASSERT_TRUE(response);
1965 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:501966 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1967 std::string response_data;
1968 rv = ReadTransaction(trans.get(), &response_data);
1969 EXPECT_EQ(OK, rv);
1970 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131971}
1972
[email protected]038e9a32008-10-08 22:40:161973// Test the request-challenge-retry sequence for basic auth.
1974// (basic auth is the easiest to mock, because it has no randomness).
[email protected]23e482282013-06-14 16:08:021975TEST_P(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421976 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161977 request.method = "GET";
bncce36dca22015-04-21 22:11:231978 request.url = GURL("http://www.example.org/");
[email protected]038e9a32008-10-08 22:40:161979 request.load_flags = 0;
1980
vishal.b62985ca92015-04-17 08:45:511981 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:071982 session_deps_.net_log = &log;
mmenkee65e7af2015-10-13 17:16:421983 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271984 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411985 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271986
[email protected]f9ee6b52008-11-08 06:46:231987 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:231988 MockWrite(
1989 "GET / HTTP/1.1\r\n"
1990 "Host: www.example.org\r\n"
1991 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:231992 };
1993
[email protected]038e9a32008-10-08 22:40:161994 MockRead data_reads1[] = {
1995 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1996 // Give a couple authenticate options (only the middle one is actually
1997 // supported).
[email protected]22927ad2009-09-21 19:56:191998 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161999 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2000 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2001 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2002 // Large content-length -- won't matter, as connection will be reset.
2003 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062004 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162005 };
2006
2007 // After calling trans->RestartWithAuth(), this is the request we should
2008 // be issuing -- the final header line contains the credentials.
2009 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232010 MockWrite(
2011 "GET / HTTP/1.1\r\n"
2012 "Host: www.example.org\r\n"
2013 "Connection: keep-alive\r\n"
2014 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162015 };
2016
2017 // Lastly, the server responds with the actual content.
2018 MockRead data_reads2[] = {
2019 MockRead("HTTP/1.0 200 OK\r\n"),
2020 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2021 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062022 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162023 };
2024
[email protected]31a2bfe2010-02-09 08:03:392025 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2026 data_writes1, arraysize(data_writes1));
2027 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2028 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:072029 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2030 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162031
[email protected]49639fa2011-12-20 23:22:412032 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162033
[email protected]49639fa2011-12-20 23:22:412034 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422035 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162036
2037 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422038 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162039
[email protected]58e32bb2013-01-21 18:23:252040 LoadTimingInfo load_timing_info1;
2041 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2042 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2043
sclittlefb249892015-09-10 21:33:222044 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2045 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2046 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
[email protected]b8015c42013-12-24 15:18:192047 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2048
[email protected]1c773ea12009-04-28 19:58:422049 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502050 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042051 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162052
[email protected]49639fa2011-12-20 23:22:412053 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162054
[email protected]49639fa2011-12-20 23:22:412055 rv = trans->RestartWithAuth(
2056 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422057 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162058
2059 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422060 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162061
[email protected]58e32bb2013-01-21 18:23:252062 LoadTimingInfo load_timing_info2;
2063 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2064 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2065 // The load timing after restart should have a new socket ID, and times after
2066 // those of the first load timing.
2067 EXPECT_LE(load_timing_info1.receive_headers_end,
2068 load_timing_info2.connect_timing.connect_start);
2069 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2070
sclittlefb249892015-09-10 21:33:222071 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2072 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2073 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
[email protected]b8015c42013-12-24 15:18:192074 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2075
[email protected]038e9a32008-10-08 22:40:162076 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502077 ASSERT_TRUE(response != NULL);
[email protected]038e9a32008-10-08 22:40:162078 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2079 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162080}
2081
ttuttled9dbc652015-09-29 20:00:592082// Test the request-challenge-retry sequence for basic auth.
2083// (basic auth is the easiest to mock, because it has no randomness).
2084TEST_P(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
2085 HttpRequestInfo request;
2086 request.method = "GET";
2087 request.url = GURL("http://www.example.org/");
2088 request.load_flags = 0;
2089
2090 TestNetLog log;
2091 MockHostResolver* resolver = new MockHostResolver();
2092 session_deps_.net_log = &log;
2093 session_deps_.host_resolver.reset(resolver);
mmenkee65e7af2015-10-13 17:16:422094 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
ttuttled9dbc652015-09-29 20:00:592095 scoped_ptr<HttpTransaction> trans(
2096 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2097
2098 resolver->rules()->ClearRules();
2099 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2100
2101 MockWrite data_writes1[] = {
2102 MockWrite("GET / HTTP/1.1\r\n"
2103 "Host: www.example.org\r\n"
2104 "Connection: keep-alive\r\n\r\n"),
2105 };
2106
2107 MockRead data_reads1[] = {
2108 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2109 // Give a couple authenticate options (only the middle one is actually
2110 // supported).
2111 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2112 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2113 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2114 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2115 // Large content-length -- won't matter, as connection will be reset.
2116 MockRead("Content-Length: 10000\r\n\r\n"),
2117 MockRead(SYNCHRONOUS, ERR_FAILED),
2118 };
2119
2120 // After calling trans->RestartWithAuth(), this is the request we should
2121 // be issuing -- the final header line contains the credentials.
2122 MockWrite data_writes2[] = {
2123 MockWrite("GET / HTTP/1.1\r\n"
2124 "Host: www.example.org\r\n"
2125 "Connection: keep-alive\r\n"
2126 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2127 };
2128
2129 // Lastly, the server responds with the actual content.
2130 MockRead data_reads2[] = {
2131 MockRead("HTTP/1.0 200 OK\r\n"),
2132 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2133 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2134 };
2135
2136 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2137 data_writes1, arraysize(data_writes1));
2138 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2139 data_writes2, arraysize(data_writes2));
2140 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2141 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2142
2143 TestCompletionCallback callback1;
2144
2145 EXPECT_EQ(OK, callback1.GetResult(trans->Start(&request, callback1.callback(),
2146 BoundNetLog())));
2147
2148 LoadTimingInfo load_timing_info1;
2149 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2150 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2151
2152 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2153 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2154 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
2155 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2156
2157 const HttpResponseInfo* response = trans->GetResponseInfo();
2158 ASSERT_TRUE(response);
2159 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2160
2161 IPEndPoint endpoint;
2162 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2163 ASSERT_FALSE(endpoint.address().empty());
2164 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2165
2166 resolver->rules()->ClearRules();
2167 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2168
2169 TestCompletionCallback callback2;
2170
2171 EXPECT_EQ(OK, callback2.GetResult(trans->RestartWithAuth(
2172 AuthCredentials(kFoo, kBar), callback2.callback())));
2173
2174 LoadTimingInfo load_timing_info2;
2175 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2176 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2177 // The load timing after restart should have a new socket ID, and times after
2178 // those of the first load timing.
2179 EXPECT_LE(load_timing_info1.receive_headers_end,
2180 load_timing_info2.connect_timing.connect_start);
2181 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2182
2183 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2184 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2185 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
2186 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2187
2188 response = trans->GetResponseInfo();
2189 ASSERT_TRUE(response);
2190 EXPECT_FALSE(response->auth_challenge.get());
2191 EXPECT_EQ(100, response->headers->GetContentLength());
2192
2193 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2194 ASSERT_FALSE(endpoint.address().empty());
2195 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2196}
2197
[email protected]23e482282013-06-14 16:08:022198TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462199 HttpRequestInfo request;
2200 request.method = "GET";
bncce36dca22015-04-21 22:11:232201 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292202 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]861fcd52009-08-26 02:33:462203
mmenkee65e7af2015-10-13 17:16:422204 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272205 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:412206 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:272207
[email protected]861fcd52009-08-26 02:33:462208 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232209 MockWrite(
2210 "GET / HTTP/1.1\r\n"
2211 "Host: www.example.org\r\n"
2212 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462213 };
2214
2215 MockRead data_reads[] = {
2216 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2217 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2218 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2219 // Large content-length -- won't matter, as connection will be reset.
2220 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062221 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462222 };
2223
[email protected]31a2bfe2010-02-09 08:03:392224 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2225 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:072226 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412227 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462228
[email protected]49639fa2011-12-20 23:22:412229 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]861fcd52009-08-26 02:33:462230 EXPECT_EQ(ERR_IO_PENDING, rv);
2231
2232 rv = callback.WaitForResult();
2233 EXPECT_EQ(0, rv);
2234
sclittlefb249892015-09-10 21:33:222235 int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes));
2236 EXPECT_EQ(writes_size, trans->GetTotalSentBytes());
2237 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
[email protected]b8015c42013-12-24 15:18:192238 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2239
[email protected]861fcd52009-08-26 02:33:462240 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502241 ASSERT_TRUE(response != NULL);
[email protected]861fcd52009-08-26 02:33:462242 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2243}
2244
[email protected]2d2697f92009-02-18 21:00:322245// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2246// connection.
[email protected]23e482282013-06-14 16:08:022247TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182248 // On the second pass, the body read of the auth challenge is synchronous, so
2249 // IsConnectedAndIdle returns false. The socket should still be drained and
2250 // reused. See http://crbug.com/544255.
2251 for (int i = 0; i < 2; ++i) {
2252 HttpRequestInfo request;
2253 request.method = "GET";
2254 request.url = GURL("http://www.example.org/");
2255 request.load_flags = 0;
[email protected]2d2697f92009-02-18 21:00:322256
mmenkecc2298e2015-12-07 18:20:182257 TestNetLog log;
2258 session_deps_.net_log = &log;
2259 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272260
mmenkecc2298e2015-12-07 18:20:182261 MockWrite data_writes[] = {
2262 MockWrite(ASYNC, 0,
2263 "GET / HTTP/1.1\r\n"
2264 "Host: www.example.org\r\n"
2265 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322266
mmenkecc2298e2015-12-07 18:20:182267 // After calling trans->RestartWithAuth(), this is the request we should
2268 // be issuing -- the final header line contains the credentials.
2269 MockWrite(ASYNC, 6,
2270 "GET / HTTP/1.1\r\n"
2271 "Host: www.example.org\r\n"
2272 "Connection: keep-alive\r\n"
2273 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2274 };
[email protected]2d2697f92009-02-18 21:00:322275
mmenkecc2298e2015-12-07 18:20:182276 MockRead data_reads[] = {
2277 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2278 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2279 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2280 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2281 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322282
mmenkecc2298e2015-12-07 18:20:182283 // Lastly, the server responds with the actual content.
2284 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2285 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2286 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2287 MockRead(ASYNC, 10, "Hello"),
2288 };
[email protected]2d2697f92009-02-18 21:00:322289
mmenkecc2298e2015-12-07 18:20:182290 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
2291 arraysize(data_writes));
2292 data.set_busy_before_sync_reads(true);
2293 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:462294
mmenkecc2298e2015-12-07 18:20:182295 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322296
mmenkecc2298e2015-12-07 18:20:182297 scoped_ptr<HttpTransaction> trans(
2298 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2299 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2300 ASSERT_EQ(OK, callback1.GetResult(rv));
[email protected]2d2697f92009-02-18 21:00:322301
mmenkecc2298e2015-12-07 18:20:182302 LoadTimingInfo load_timing_info1;
2303 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2304 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:322305
mmenkecc2298e2015-12-07 18:20:182306 const HttpResponseInfo* response = trans->GetResponseInfo();
2307 ASSERT_TRUE(response);
2308 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322309
mmenkecc2298e2015-12-07 18:20:182310 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:252311
mmenkecc2298e2015-12-07 18:20:182312 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
2313 callback2.callback());
2314 ASSERT_EQ(OK, callback2.GetResult(rv));
[email protected]2d2697f92009-02-18 21:00:322315
mmenkecc2298e2015-12-07 18:20:182316 LoadTimingInfo load_timing_info2;
2317 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2318 TestLoadTimingReused(load_timing_info2);
2319 // The load timing after restart should have the same socket ID, and times
2320 // those of the first load timing.
2321 EXPECT_LE(load_timing_info1.receive_headers_end,
2322 load_timing_info2.send_start);
2323 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:322324
mmenkecc2298e2015-12-07 18:20:182325 response = trans->GetResponseInfo();
2326 ASSERT_TRUE(response);
2327 EXPECT_FALSE(response->auth_challenge);
2328 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322329
mmenkecc2298e2015-12-07 18:20:182330 std::string response_data;
2331 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]2d2697f92009-02-18 21:00:322332
mmenkecc2298e2015-12-07 18:20:182333 int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes));
2334 EXPECT_EQ(writes_size, trans->GetTotalSentBytes());
2335 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
2336 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2337 }
[email protected]2d2697f92009-02-18 21:00:322338}
2339
2340// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2341// connection and with no response body to drain.
[email protected]23e482282013-06-14 16:08:022342TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:422343 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322344 request.method = "GET";
bncce36dca22015-04-21 22:11:232345 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322346 request.load_flags = 0;
2347
mmenkee65e7af2015-10-13 17:16:422348 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272349
[email protected]2d2697f92009-02-18 21:00:322350 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232351 MockWrite(
2352 "GET / HTTP/1.1\r\n"
2353 "Host: www.example.org\r\n"
2354 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322355
bncce36dca22015-04-21 22:11:232356 // After calling trans->RestartWithAuth(), this is the request we should
2357 // be issuing -- the final header line contains the credentials.
2358 MockWrite(
2359 "GET / HTTP/1.1\r\n"
2360 "Host: www.example.org\r\n"
2361 "Connection: keep-alive\r\n"
2362 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322363 };
2364
[email protected]2d2697f92009-02-18 21:00:322365 MockRead data_reads1[] = {
2366 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2367 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:312368 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:322369
2370 // Lastly, the server responds with the actual content.
2371 MockRead("HTTP/1.1 200 OK\r\n"),
2372 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502373 MockRead("Content-Length: 5\r\n\r\n"),
2374 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322375 };
2376
[email protected]2d0a4f92011-05-05 16:38:462377 // An incorrect reconnect would cause this to be read.
2378 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062379 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462380 };
2381
[email protected]31a2bfe2010-02-09 08:03:392382 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2383 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462384 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2385 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072386 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2387 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322388
[email protected]49639fa2011-12-20 23:22:412389 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322390
[email protected]262eec82013-03-19 21:01:362391 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502392 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412393 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422394 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322395
2396 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422397 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322398
[email protected]1c773ea12009-04-28 19:58:422399 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502400 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042401 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322402
[email protected]49639fa2011-12-20 23:22:412403 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322404
[email protected]49639fa2011-12-20 23:22:412405 rv = trans->RestartWithAuth(
2406 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422407 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322408
2409 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422410 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322411
2412 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502413 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322414 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502415 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322416}
2417
2418// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2419// connection and with a large response body to drain.
[email protected]23e482282013-06-14 16:08:022420TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:422421 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322422 request.method = "GET";
bncce36dca22015-04-21 22:11:232423 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322424 request.load_flags = 0;
2425
mmenkee65e7af2015-10-13 17:16:422426 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272427
[email protected]2d2697f92009-02-18 21:00:322428 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232429 MockWrite(
2430 "GET / HTTP/1.1\r\n"
2431 "Host: www.example.org\r\n"
2432 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322433
bncce36dca22015-04-21 22:11:232434 // After calling trans->RestartWithAuth(), this is the request we should
2435 // be issuing -- the final header line contains the credentials.
2436 MockWrite(
2437 "GET / HTTP/1.1\r\n"
2438 "Host: www.example.org\r\n"
2439 "Connection: keep-alive\r\n"
2440 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322441 };
2442
2443 // Respond with 5 kb of response body.
2444 std::string large_body_string("Unauthorized");
2445 large_body_string.append(5 * 1024, ' ');
2446 large_body_string.append("\r\n");
2447
2448 MockRead data_reads1[] = {
2449 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2450 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2451 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2452 // 5134 = 12 + 5 * 1024 + 2
2453 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062454 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:322455
2456 // Lastly, the server responds with the actual content.
2457 MockRead("HTTP/1.1 200 OK\r\n"),
2458 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502459 MockRead("Content-Length: 5\r\n\r\n"),
2460 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322461 };
2462
[email protected]2d0a4f92011-05-05 16:38:462463 // An incorrect reconnect would cause this to be read.
2464 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062465 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462466 };
2467
[email protected]31a2bfe2010-02-09 08:03:392468 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2469 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462470 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2471 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072472 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2473 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322474
[email protected]49639fa2011-12-20 23:22:412475 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322476
[email protected]262eec82013-03-19 21:01:362477 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502478 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412479 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422480 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322481
2482 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422483 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322484
[email protected]1c773ea12009-04-28 19:58:422485 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502486 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042487 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322488
[email protected]49639fa2011-12-20 23:22:412489 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322490
[email protected]49639fa2011-12-20 23:22:412491 rv = trans->RestartWithAuth(
2492 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422493 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322494
2495 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422496 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322497
2498 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502499 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322500 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502501 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322502}
2503
2504// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:312505// connection, but the server gets impatient and closes the connection.
[email protected]23e482282013-06-14 16:08:022506TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:312507 HttpRequestInfo request;
2508 request.method = "GET";
bncce36dca22015-04-21 22:11:232509 request.url = GURL("http://www.example.org/");
[email protected]11203f012009-11-12 23:02:312510 request.load_flags = 0;
2511
mmenkee65e7af2015-10-13 17:16:422512 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272513
[email protected]11203f012009-11-12 23:02:312514 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232515 MockWrite(
2516 "GET / HTTP/1.1\r\n"
2517 "Host: www.example.org\r\n"
2518 "Connection: keep-alive\r\n\r\n"),
2519 // This simulates the seemingly successful write to a closed connection
2520 // if the bug is not fixed.
2521 MockWrite(
2522 "GET / HTTP/1.1\r\n"
2523 "Host: www.example.org\r\n"
2524 "Connection: keep-alive\r\n"
2525 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312526 };
2527
2528 MockRead data_reads1[] = {
2529 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2530 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2531 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2532 MockRead("Content-Length: 14\r\n\r\n"),
2533 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:062534 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:312535 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:062536 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:312537 };
2538
2539 // After calling trans->RestartWithAuth(), this is the request we should
2540 // be issuing -- the final header line contains the credentials.
2541 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232542 MockWrite(
2543 "GET / HTTP/1.1\r\n"
2544 "Host: www.example.org\r\n"
2545 "Connection: keep-alive\r\n"
2546 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312547 };
2548
2549 // Lastly, the server responds with the actual content.
2550 MockRead data_reads2[] = {
2551 MockRead("HTTP/1.1 200 OK\r\n"),
2552 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502553 MockRead("Content-Length: 5\r\n\r\n"),
2554 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:312555 };
2556
[email protected]31a2bfe2010-02-09 08:03:392557 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2558 data_writes1, arraysize(data_writes1));
2559 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2560 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:072561 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2562 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:312563
[email protected]49639fa2011-12-20 23:22:412564 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:312565
[email protected]262eec82013-03-19 21:01:362566 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502567 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412568 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]11203f012009-11-12 23:02:312569 EXPECT_EQ(ERR_IO_PENDING, rv);
2570
2571 rv = callback1.WaitForResult();
2572 EXPECT_EQ(OK, rv);
2573
2574 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502575 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042576 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]11203f012009-11-12 23:02:312577
[email protected]49639fa2011-12-20 23:22:412578 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:312579
[email protected]49639fa2011-12-20 23:22:412580 rv = trans->RestartWithAuth(
2581 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]11203f012009-11-12 23:02:312582 EXPECT_EQ(ERR_IO_PENDING, rv);
2583
2584 rv = callback2.WaitForResult();
2585 EXPECT_EQ(OK, rv);
2586
2587 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502588 ASSERT_TRUE(response != NULL);
[email protected]11203f012009-11-12 23:02:312589 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502590 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:312591}
2592
[email protected]394816e92010-08-03 07:38:592593// Test the request-challenge-retry sequence for basic auth, over a connection
2594// that requires a restart when setting up an SSL tunnel.
ttuttle34f63b52015-03-05 04:33:012595TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
2596 HttpRequestInfo request;
2597 request.method = "GET";
bncce36dca22015-04-21 22:11:232598 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:012599 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292600 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:012601
2602 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032603 session_deps_.proxy_service =
2604 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512605 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:012606 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:422607 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:012608
2609 // Since we have proxy, should try to establish tunnel.
2610 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542611 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172612 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542613 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:012614 };
2615
mmenkee71e15332015-10-07 16:39:542616 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:012617 // connection.
2618 MockRead data_reads1[] = {
2619 // No credentials.
2620 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2621 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:542622 };
ttuttle34f63b52015-03-05 04:33:012623
mmenkee71e15332015-10-07 16:39:542624 // Since the first connection couldn't be reused, need to establish another
2625 // once given credentials.
2626 MockWrite data_writes2[] = {
2627 // After calling trans->RestartWithAuth(), this is the request we should
2628 // be issuing -- the final header line contains the credentials.
2629 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172630 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542631 "Proxy-Connection: keep-alive\r\n"
2632 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2633
2634 MockWrite("GET / HTTP/1.1\r\n"
2635 "Host: www.example.org\r\n"
2636 "Connection: keep-alive\r\n\r\n"),
2637 };
2638
2639 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:012640 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2641
2642 MockRead("HTTP/1.1 200 OK\r\n"),
2643 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2644 MockRead("Content-Length: 5\r\n\r\n"),
2645 MockRead(SYNCHRONOUS, "hello"),
2646 };
2647
2648 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2649 data_writes1, arraysize(data_writes1));
2650 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542651 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2652 data_writes2, arraysize(data_writes2));
2653 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:012654 SSLSocketDataProvider ssl(ASYNC, OK);
2655 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2656
2657 TestCompletionCallback callback1;
2658
2659 scoped_ptr<HttpTransaction> trans(
2660 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2661
2662 int rv = trans->Start(&request, callback1.callback(), log.bound());
2663 EXPECT_EQ(ERR_IO_PENDING, rv);
2664
2665 rv = callback1.WaitForResult();
2666 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462667 TestNetLogEntry::List entries;
ttuttle34f63b52015-03-05 04:33:012668 log.GetEntries(&entries);
2669 size_t pos = ExpectLogContainsSomewhere(
2670 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2671 NetLog::PHASE_NONE);
2672 ExpectLogContainsSomewhere(
2673 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2674 NetLog::PHASE_NONE);
2675
2676 const HttpResponseInfo* response = trans->GetResponseInfo();
2677 ASSERT_TRUE(response != NULL);
2678 EXPECT_FALSE(response->headers->IsKeepAlive());
2679 ASSERT_FALSE(response->headers.get() == NULL);
2680 EXPECT_EQ(407, response->headers->response_code());
2681 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2682 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2683
2684 LoadTimingInfo load_timing_info;
2685 // CONNECT requests and responses are handled at the connect job level, so
2686 // the transaction does not yet have a connection.
2687 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2688
2689 TestCompletionCallback callback2;
2690
2691 rv =
2692 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
2693 EXPECT_EQ(ERR_IO_PENDING, rv);
2694
2695 rv = callback2.WaitForResult();
2696 EXPECT_EQ(OK, rv);
2697
2698 response = trans->GetResponseInfo();
2699 ASSERT_TRUE(response != NULL);
2700
2701 EXPECT_TRUE(response->headers->IsKeepAlive());
2702 EXPECT_EQ(200, response->headers->response_code());
2703 EXPECT_EQ(5, response->headers->GetContentLength());
2704 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2705
2706 // The password prompt info should not be set.
2707 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2708
2709 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2710 TestLoadTimingNotReusedWithPac(load_timing_info,
2711 CONNECT_TIMING_HAS_SSL_TIMES);
2712
2713 trans.reset();
2714 session->CloseAllConnections();
2715}
2716
2717// Test the request-challenge-retry sequence for basic auth, over a connection
2718// that requires a restart when setting up an SSL tunnel.
2719TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:592720 HttpRequestInfo request;
2721 request.method = "GET";
bncce36dca22015-04-21 22:11:232722 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:592723 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292724 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]394816e92010-08-03 07:38:592725
[email protected]cb9bf6ca2011-01-28 13:15:272726 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032727 session_deps_.proxy_service =
2728 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512729 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072730 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:422731 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272732
[email protected]394816e92010-08-03 07:38:592733 // Since we have proxy, should try to establish tunnel.
2734 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542735 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172736 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542737 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:112738 };
2739
mmenkee71e15332015-10-07 16:39:542740 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:082741 // connection.
2742 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:542743 // No credentials.
2744 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2745 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2746 MockRead("Proxy-Connection: close\r\n\r\n"),
2747 };
mmenkee0b5c882015-08-26 20:29:112748
mmenkee71e15332015-10-07 16:39:542749 MockWrite data_writes2[] = {
2750 // After calling trans->RestartWithAuth(), this is the request we should
2751 // be issuing -- the final header line contains the credentials.
2752 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172753 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542754 "Proxy-Connection: keep-alive\r\n"
2755 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:082756
mmenkee71e15332015-10-07 16:39:542757 MockWrite("GET / HTTP/1.1\r\n"
2758 "Host: www.example.org\r\n"
2759 "Connection: keep-alive\r\n\r\n"),
2760 };
2761
2762 MockRead data_reads2[] = {
2763 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2764
2765 MockRead("HTTP/1.1 200 OK\r\n"),
2766 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2767 MockRead("Content-Length: 5\r\n\r\n"),
2768 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:592769 };
2770
2771 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2772 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:072773 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542774 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2775 data_writes2, arraysize(data_writes2));
2776 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:062777 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:072778 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:592779
[email protected]49639fa2011-12-20 23:22:412780 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:592781
[email protected]262eec82013-03-19 21:01:362782 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502783 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:502784
[email protected]49639fa2011-12-20 23:22:412785 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]394816e92010-08-03 07:38:592786 EXPECT_EQ(ERR_IO_PENDING, rv);
2787
2788 rv = callback1.WaitForResult();
2789 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462790 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:402791 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:592792 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402793 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:592794 NetLog::PHASE_NONE);
2795 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402796 entries, pos,
[email protected]394816e92010-08-03 07:38:592797 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2798 NetLog::PHASE_NONE);
2799
2800 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502801 ASSERT_TRUE(response != NULL);
ttuttle34f63b52015-03-05 04:33:012802 EXPECT_FALSE(response->headers->IsKeepAlive());
[email protected]90499482013-06-01 00:39:502803 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]394816e92010-08-03 07:38:592804 EXPECT_EQ(407, response->headers->response_code());
2805 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042806 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]394816e92010-08-03 07:38:592807
[email protected]029c83b62013-01-24 05:28:202808 LoadTimingInfo load_timing_info;
2809 // CONNECT requests and responses are handled at the connect job level, so
2810 // the transaction does not yet have a connection.
2811 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2812
[email protected]49639fa2011-12-20 23:22:412813 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:592814
[email protected]49639fa2011-12-20 23:22:412815 rv = trans->RestartWithAuth(
2816 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]394816e92010-08-03 07:38:592817 EXPECT_EQ(ERR_IO_PENDING, rv);
2818
2819 rv = callback2.WaitForResult();
2820 EXPECT_EQ(OK, rv);
2821
2822 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502823 ASSERT_TRUE(response != NULL);
[email protected]394816e92010-08-03 07:38:592824
2825 EXPECT_TRUE(response->headers->IsKeepAlive());
2826 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:502827 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:592828 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2829
2830 // The password prompt info should not be set.
2831 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502832
[email protected]029c83b62013-01-24 05:28:202833 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2834 TestLoadTimingNotReusedWithPac(load_timing_info,
2835 CONNECT_TIMING_HAS_SSL_TIMES);
2836
[email protected]0b0bf032010-09-21 18:08:502837 trans.reset();
[email protected]102e27c2011-02-23 01:01:312838 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:592839}
2840
[email protected]11203f012009-11-12 23:02:312841// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:012842// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2843TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:232844 // On the second pass, the body read of the auth challenge is synchronous, so
2845 // IsConnectedAndIdle returns false. The socket should still be drained and
2846 // reused. See http://crbug.com/544255.
2847 for (int i = 0; i < 2; ++i) {
2848 HttpRequestInfo request;
2849 request.method = "GET";
2850 request.url = GURL("https://www.example.org/");
2851 // Ensure that proxy authentication is attempted even
2852 // when the no authentication data flag is set.
2853 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:012854
mmenked39192ee2015-12-09 00:57:232855 // Configure against proxy server "myproxy:70".
2856 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
2857 BoundTestNetLog log;
2858 session_deps_.net_log = log.bound().net_log();
2859 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:012860
mmenked39192ee2015-12-09 00:57:232861 scoped_ptr<HttpTransaction> trans(
2862 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
ttuttle34f63b52015-03-05 04:33:012863
mmenked39192ee2015-12-09 00:57:232864 // Since we have proxy, should try to establish tunnel.
2865 MockWrite data_writes1[] = {
2866 MockWrite(ASYNC, 0,
2867 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2868 "Host: www.example.org:443\r\n"
2869 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:012870
mmenked39192ee2015-12-09 00:57:232871 // After calling trans->RestartWithAuth(), this is the request we should
2872 // be issuing -- the final header line contains the credentials.
2873 MockWrite(ASYNC, 3,
2874 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2875 "Host: www.example.org:443\r\n"
2876 "Proxy-Connection: keep-alive\r\n"
2877 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2878 };
ttuttle34f63b52015-03-05 04:33:012879
mmenked39192ee2015-12-09 00:57:232880 // The proxy responds to the connect with a 407, using a persistent
2881 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2882 MockRead data_reads1[] = {
2883 // No credentials.
2884 MockRead(ASYNC, 1,
2885 "HTTP/1.0 407 Proxy Authentication Required\r\n"
2886 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
2887 "Proxy-Connection: keep-alive\r\n"
2888 "Content-Length: 10\r\n\r\n"),
2889 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:012890
mmenked39192ee2015-12-09 00:57:232891 // Wrong credentials (wrong password).
2892 MockRead(ASYNC, 4,
2893 "HTTP/1.0 407 Proxy Authentication Required\r\n"
2894 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
2895 "Proxy-Connection: keep-alive\r\n"
2896 "Content-Length: 10\r\n\r\n"),
2897 // No response body because the test stops reading here.
2898 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
2899 };
ttuttle34f63b52015-03-05 04:33:012900
mmenked39192ee2015-12-09 00:57:232901 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
2902 arraysize(data_writes1));
2903 data1.set_busy_before_sync_reads(true);
2904 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:012905
mmenked39192ee2015-12-09 00:57:232906 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:012907
mmenked39192ee2015-12-09 00:57:232908 int rv = trans->Start(&request, callback1.callback(), log.bound());
2909 EXPECT_EQ(OK, callback1.GetResult(rv));
ttuttle34f63b52015-03-05 04:33:012910
mmenked39192ee2015-12-09 00:57:232911 TestNetLogEntry::List entries;
2912 log.GetEntries(&entries);
2913 size_t pos = ExpectLogContainsSomewhere(
2914 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2915 NetLog::PHASE_NONE);
2916 ExpectLogContainsSomewhere(
2917 entries, pos,
2918 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2919 NetLog::PHASE_NONE);
ttuttle34f63b52015-03-05 04:33:012920
mmenked39192ee2015-12-09 00:57:232921 const HttpResponseInfo* response = trans->GetResponseInfo();
2922 ASSERT_TRUE(response);
2923 ASSERT_TRUE(response->headers);
2924 EXPECT_TRUE(response->headers->IsKeepAlive());
2925 EXPECT_EQ(407, response->headers->response_code());
2926 EXPECT_EQ(10, response->headers->GetContentLength());
2927 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2928 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
ttuttle34f63b52015-03-05 04:33:012929
mmenked39192ee2015-12-09 00:57:232930 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:012931
mmenked39192ee2015-12-09 00:57:232932 // Wrong password (should be "bar").
2933 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBaz),
2934 callback2.callback());
2935 EXPECT_EQ(OK, callback2.GetResult(rv));
ttuttle34f63b52015-03-05 04:33:012936
mmenked39192ee2015-12-09 00:57:232937 response = trans->GetResponseInfo();
2938 ASSERT_TRUE(response);
2939 ASSERT_TRUE(response->headers);
2940 EXPECT_TRUE(response->headers->IsKeepAlive());
2941 EXPECT_EQ(407, response->headers->response_code());
2942 EXPECT_EQ(10, response->headers->GetContentLength());
2943 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2944 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
ttuttle34f63b52015-03-05 04:33:012945
mmenked39192ee2015-12-09 00:57:232946 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2947 // out of scope.
2948 session->CloseAllConnections();
2949 }
ttuttle34f63b52015-03-05 04:33:012950}
2951
2952// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2953// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2954TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:232955 // On the second pass, the body read of the auth challenge is synchronous, so
2956 // IsConnectedAndIdle returns false. The socket should still be drained and
2957 // reused. See http://crbug.com/544255.
2958 for (int i = 0; i < 2; ++i) {
2959 HttpRequestInfo request;
2960 request.method = "GET";
2961 request.url = GURL("https://www.example.org/");
2962 // Ensure that proxy authentication is attempted even
2963 // when the no authentication data flag is set.
2964 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2965
2966 // Configure against proxy server "myproxy:70".
2967 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
2968 BoundTestNetLog log;
2969 session_deps_.net_log = log.bound().net_log();
2970 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2971
2972 scoped_ptr<HttpTransaction> trans(
2973 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2974
2975 // Since we have proxy, should try to establish tunnel.
2976 MockWrite data_writes1[] = {
2977 MockWrite(ASYNC, 0,
2978 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2979 "Host: www.example.org:443\r\n"
2980 "Proxy-Connection: keep-alive\r\n\r\n"),
2981
2982 // After calling trans->RestartWithAuth(), this is the request we should
2983 // be issuing -- the final header line contains the credentials.
2984 MockWrite(ASYNC, 3,
2985 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2986 "Host: www.example.org:443\r\n"
2987 "Proxy-Connection: keep-alive\r\n"
2988 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2989 };
2990
2991 // The proxy responds to the connect with a 407, using a persistent
2992 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2993 MockRead data_reads1[] = {
2994 // No credentials.
2995 MockRead(ASYNC, 1,
2996 "HTTP/1.1 407 Proxy Authentication Required\r\n"
2997 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
2998 "Content-Length: 10\r\n\r\n"),
2999 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3000
3001 // Wrong credentials (wrong password).
3002 MockRead(ASYNC, 4,
3003 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3004 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3005 "Content-Length: 10\r\n\r\n"),
3006 // No response body because the test stops reading here.
3007 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3008 };
3009
3010 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
3011 arraysize(data_writes1));
3012 data1.set_busy_before_sync_reads(true);
3013 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3014
3015 TestCompletionCallback callback1;
3016
3017 int rv = trans->Start(&request, callback1.callback(), log.bound());
3018 EXPECT_EQ(OK, callback1.GetResult(rv));
3019
3020 TestNetLogEntry::List entries;
3021 log.GetEntries(&entries);
3022 size_t pos = ExpectLogContainsSomewhere(
3023 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3024 NetLog::PHASE_NONE);
3025 ExpectLogContainsSomewhere(
3026 entries, pos,
3027 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3028 NetLog::PHASE_NONE);
3029
3030 const HttpResponseInfo* response = trans->GetResponseInfo();
3031 ASSERT_TRUE(response);
3032 ASSERT_TRUE(response->headers);
3033 EXPECT_TRUE(response->headers->IsKeepAlive());
3034 EXPECT_EQ(407, response->headers->response_code());
3035 EXPECT_EQ(10, response->headers->GetContentLength());
3036 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3037 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3038
3039 TestCompletionCallback callback2;
3040
3041 // Wrong password (should be "bar").
3042 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBaz),
3043 callback2.callback());
3044 EXPECT_EQ(OK, callback2.GetResult(rv));
3045
3046 response = trans->GetResponseInfo();
3047 ASSERT_TRUE(response);
3048 ASSERT_TRUE(response->headers);
3049 EXPECT_TRUE(response->headers->IsKeepAlive());
3050 EXPECT_EQ(407, response->headers->response_code());
3051 EXPECT_EQ(10, response->headers->GetContentLength());
3052 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3053 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3054
3055 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3056 // out of scope.
3057 session->CloseAllConnections();
3058 }
3059}
3060
3061// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3062// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3063// the case the server sends extra data on the original socket, so it can't be
3064// reused.
3065TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273066 HttpRequestInfo request;
3067 request.method = "GET";
bncce36dca22015-04-21 22:11:233068 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273069 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293070 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]cb9bf6ca2011-01-28 13:15:273071
[email protected]2d2697f92009-02-18 21:00:323072 // Configure against proxy server "myproxy:70".
mmenked39192ee2015-12-09 00:57:233073 session_deps_.proxy_service =
3074 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:513075 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073076 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423077 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323078
[email protected]2d2697f92009-02-18 21:00:323079 // Since we have proxy, should try to establish tunnel.
3080 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233081 MockWrite(ASYNC, 0,
3082 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173083 "Host: www.example.org:443\r\n"
3084 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233085 };
[email protected]2d2697f92009-02-18 21:00:323086
mmenked39192ee2015-12-09 00:57:233087 // The proxy responds to the connect with a 407, using a persistent, but sends
3088 // extra data, so the socket cannot be reused.
3089 MockRead data_reads1[] = {
3090 // No credentials.
3091 MockRead(ASYNC, 1,
3092 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3093 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3094 "Content-Length: 10\r\n\r\n"),
3095 MockRead(SYNCHRONOUS, 2, "0123456789"),
3096 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3097 };
3098
3099 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233100 // After calling trans->RestartWithAuth(), this is the request we should
3101 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233102 MockWrite(ASYNC, 0,
3103 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173104 "Host: www.example.org:443\r\n"
3105 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233106 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3107
3108 MockWrite(ASYNC, 2,
3109 "GET / HTTP/1.1\r\n"
3110 "Host: www.example.org\r\n"
3111 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323112 };
3113
mmenked39192ee2015-12-09 00:57:233114 MockRead data_reads2[] = {
3115 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323116
mmenked39192ee2015-12-09 00:57:233117 MockRead(ASYNC, 3,
3118 "HTTP/1.1 200 OK\r\n"
3119 "Content-Type: text/html; charset=iso-8859-1\r\n"
3120 "Content-Length: 5\r\n\r\n"),
3121 // No response body because the test stops reading here.
3122 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323123 };
3124
mmenked39192ee2015-12-09 00:57:233125 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
3126 arraysize(data_writes1));
3127 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073128 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenked39192ee2015-12-09 00:57:233129 SequencedSocketData data2(data_reads2, arraysize(data_reads2), data_writes2,
3130 arraysize(data_writes2));
3131 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3132 SSLSocketDataProvider ssl(ASYNC, OK);
3133 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323134
[email protected]49639fa2011-12-20 23:22:413135 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323136
mmenked39192ee2015-12-09 00:57:233137 scoped_ptr<HttpTransaction> trans(
3138 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d2697f92009-02-18 21:00:323139
mmenked39192ee2015-12-09 00:57:233140 int rv = trans->Start(&request, callback1.callback(), log.bound());
3141 EXPECT_EQ(OK, callback1.GetResult(rv));
3142
mmenke43758e62015-05-04 21:09:463143 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403144 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:393145 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403146 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:393147 NetLog::PHASE_NONE);
3148 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403149 entries, pos,
[email protected]dbb83db2010-05-11 18:13:393150 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3151 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:323152
[email protected]1c773ea12009-04-28 19:58:423153 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243154 ASSERT_TRUE(response);
3155 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323156 EXPECT_TRUE(response->headers->IsKeepAlive());
3157 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423158 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:043159 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:323160
mmenked39192ee2015-12-09 00:57:233161 LoadTimingInfo load_timing_info;
3162 // CONNECT requests and responses are handled at the connect job level, so
3163 // the transaction does not yet have a connection.
3164 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3165
[email protected]49639fa2011-12-20 23:22:413166 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323167
mmenked39192ee2015-12-09 00:57:233168 rv =
3169 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
3170 EXPECT_EQ(OK, callback2.GetResult(rv));
[email protected]2d2697f92009-02-18 21:00:323171
[email protected]2d2697f92009-02-18 21:00:323172 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233173 EXPECT_EQ(200, response->headers->response_code());
3174 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423175 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133176
mmenked39192ee2015-12-09 00:57:233177 // The password prompt info should not be set.
3178 EXPECT_FALSE(response->auth_challenge);
3179
3180 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3181 TestLoadTimingNotReusedWithPac(load_timing_info,
3182 CONNECT_TIMING_HAS_SSL_TIMES);
3183
3184 trans.reset();
[email protected]102e27c2011-02-23 01:01:313185 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323186}
3187
mmenkee71e15332015-10-07 16:39:543188// Test the case a proxy closes a socket while the challenge body is being
3189// drained.
3190TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
3191 HttpRequestInfo request;
3192 request.method = "GET";
3193 request.url = GURL("https://www.example.org/");
3194 // Ensure that proxy authentication is attempted even
3195 // when the no authentication data flag is set.
3196 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
3197
3198 // Configure against proxy server "myproxy:70".
3199 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:423200 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543201
3202 scoped_ptr<HttpTransaction> trans(
3203 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3204
3205 // Since we have proxy, should try to establish tunnel.
3206 MockWrite data_writes1[] = {
3207 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173208 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543209 "Proxy-Connection: keep-alive\r\n\r\n"),
3210 };
3211
3212 // The proxy responds to the connect with a 407, using a persistent
3213 // connection.
3214 MockRead data_reads1[] = {
3215 // No credentials.
3216 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3217 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3218 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3219 // Server hands up in the middle of the body.
3220 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3221 };
3222
3223 MockWrite data_writes2[] = {
3224 // After calling trans->RestartWithAuth(), this is the request we should
3225 // be issuing -- the final header line contains the credentials.
3226 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173227 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543228 "Proxy-Connection: keep-alive\r\n"
3229 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3230
3231 MockWrite("GET / HTTP/1.1\r\n"
3232 "Host: www.example.org\r\n"
3233 "Connection: keep-alive\r\n\r\n"),
3234 };
3235
3236 MockRead data_reads2[] = {
3237 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3238
3239 MockRead("HTTP/1.1 200 OK\r\n"),
3240 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3241 MockRead("Content-Length: 5\r\n\r\n"),
3242 MockRead(SYNCHRONOUS, "hello"),
3243 };
3244
3245 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3246 data_writes1, arraysize(data_writes1));
3247 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3248 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3249 data_writes2, arraysize(data_writes2));
3250 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3251 SSLSocketDataProvider ssl(ASYNC, OK);
3252 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3253
3254 TestCompletionCallback callback;
3255
3256 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3257 EXPECT_EQ(OK, callback.GetResult(rv));
3258
3259 const HttpResponseInfo* response = trans->GetResponseInfo();
3260 ASSERT_TRUE(response);
3261 ASSERT_TRUE(response->headers);
3262 EXPECT_TRUE(response->headers->IsKeepAlive());
3263 EXPECT_EQ(407, response->headers->response_code());
3264 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3265
3266 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
3267 EXPECT_EQ(OK, callback.GetResult(rv));
3268
3269 response = trans->GetResponseInfo();
3270 ASSERT_TRUE(response);
3271 ASSERT_TRUE(response->headers);
3272 EXPECT_TRUE(response->headers->IsKeepAlive());
3273 EXPECT_EQ(200, response->headers->response_code());
3274 std::string body;
3275 EXPECT_EQ(OK, ReadTransaction(trans.get(), &body));
3276 EXPECT_EQ("hello", body);
3277}
3278
[email protected]a8e9b162009-03-12 00:06:443279// Test that we don't read the response body when we fail to establish a tunnel,
3280// even if the user cancels the proxy's auth attempt.
[email protected]23e482282013-06-14 16:08:023281TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273282 HttpRequestInfo request;
3283 request.method = "GET";
bncce36dca22015-04-21 22:11:233284 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273285 request.load_flags = 0;
3286
[email protected]a8e9b162009-03-12 00:06:443287 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033288 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]a8e9b162009-03-12 00:06:443289
mmenkee65e7af2015-10-13 17:16:423290 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443291
[email protected]262eec82013-03-19 21:01:363292 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503293 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]a8e9b162009-03-12 00:06:443294
[email protected]a8e9b162009-03-12 00:06:443295 // Since we have proxy, should try to establish tunnel.
3296 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173297 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3298 "Host: www.example.org:443\r\n"
3299 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443300 };
3301
3302 // The proxy responds to the connect with a 407.
3303 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243304 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3305 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3306 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233307 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:243308 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443309 };
3310
[email protected]31a2bfe2010-02-09 08:03:393311 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3312 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:073313 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443314
[email protected]49639fa2011-12-20 23:22:413315 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443316
[email protected]49639fa2011-12-20 23:22:413317 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423318 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:443319
3320 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423321 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:443322
[email protected]1c773ea12009-04-28 19:58:423323 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243324 ASSERT_TRUE(response);
3325 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:443326 EXPECT_TRUE(response->headers->IsKeepAlive());
3327 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423328 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:443329
3330 std::string response_data;
3331 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423332 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:183333
3334 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:313335 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:443336}
3337
ttuttle7933c112015-01-06 00:55:243338// Test that we don't pass extraneous headers from the proxy's response to the
3339// caller when the proxy responds to CONNECT with 407.
3340TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
3341 HttpRequestInfo request;
3342 request.method = "GET";
bncce36dca22015-04-21 22:11:233343 request.url = GURL("https://www.example.org/");
ttuttle7933c112015-01-06 00:55:243344 request.load_flags = 0;
3345
3346 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033347 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
ttuttle7933c112015-01-06 00:55:243348
mmenkee65e7af2015-10-13 17:16:423349 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:243350
3351 scoped_ptr<HttpTransaction> trans(
3352 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3353
3354 // Since we have proxy, should try to establish tunnel.
3355 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173356 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3357 "Host: www.example.org:443\r\n"
3358 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:243359 };
3360
3361 // The proxy responds to the connect with a 407.
3362 MockRead data_reads[] = {
3363 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3364 MockRead("X-Foo: bar\r\n"),
3365 MockRead("Set-Cookie: foo=bar\r\n"),
3366 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3367 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233368 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:243369 };
3370
3371 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
3372 arraysize(data_writes));
3373 session_deps_.socket_factory->AddSocketDataProvider(&data);
3374
3375 TestCompletionCallback callback;
3376
3377 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3378 EXPECT_EQ(ERR_IO_PENDING, rv);
3379
3380 rv = callback.WaitForResult();
3381 EXPECT_EQ(OK, rv);
3382
3383 const HttpResponseInfo* response = trans->GetResponseInfo();
3384 ASSERT_TRUE(response);
3385 ASSERT_TRUE(response->headers);
3386 EXPECT_TRUE(response->headers->IsKeepAlive());
3387 EXPECT_EQ(407, response->headers->response_code());
3388 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3389 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
3390 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
3391
3392 std::string response_data;
3393 rv = ReadTransaction(trans.get(), &response_data);
3394 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3395
3396 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3397 session->CloseAllConnections();
3398}
3399
[email protected]8fdbcd22010-05-05 02:54:523400// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
3401// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
[email protected]23e482282013-06-14 16:08:023402TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:523403 HttpRequestInfo request;
3404 request.method = "GET";
bncce36dca22015-04-21 22:11:233405 request.url = GURL("http://www.example.org/");
[email protected]8fdbcd22010-05-05 02:54:523406 request.load_flags = 0;
3407
[email protected]cb9bf6ca2011-01-28 13:15:273408 // We are using a DIRECT connection (i.e. no proxy) for this session.
mmenkee65e7af2015-10-13 17:16:423409 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273410 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:413411 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:273412
[email protected]8fdbcd22010-05-05 02:54:523413 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233414 MockWrite(
3415 "GET / HTTP/1.1\r\n"
3416 "Host: www.example.org\r\n"
3417 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:523418 };
3419
3420 MockRead data_reads1[] = {
3421 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
3422 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3423 // Large content-length -- won't matter, as connection will be reset.
3424 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063425 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:523426 };
3427
3428 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3429 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073430 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:523431
[email protected]49639fa2011-12-20 23:22:413432 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:523433
[email protected]49639fa2011-12-20 23:22:413434 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]8fdbcd22010-05-05 02:54:523435 EXPECT_EQ(ERR_IO_PENDING, rv);
3436
3437 rv = callback.WaitForResult();
3438 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3439}
3440
[email protected]7a67a8152010-11-05 18:31:103441// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3442// through a non-authenticating proxy. The request should fail with
3443// ERR_UNEXPECTED_PROXY_AUTH.
3444// Note that it is impossible to detect if an HTTP server returns a 407 through
3445// a non-authenticating proxy - there is nothing to indicate whether the
3446// response came from the proxy or the server, so it is treated as if the proxy
3447// issued the challenge.
[email protected]23e482282013-06-14 16:08:023448TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:233449 HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:273450 HttpRequestInfo request;
3451 request.method = "GET";
bncce36dca22015-04-21 22:11:233452 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273453
rdsmith82957ad2015-09-16 19:42:033454 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:513455 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073456 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423457 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:103458
[email protected]7a67a8152010-11-05 18:31:103459 // Since we have proxy, should try to establish tunnel.
3460 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:173461 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3462 "Host: www.example.org:443\r\n"
3463 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103464
rsleevidb16bb02015-11-12 23:47:173465 MockWrite("GET / HTTP/1.1\r\n"
3466 "Host: www.example.org\r\n"
3467 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103468 };
3469
3470 MockRead data_reads1[] = {
3471 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3472
3473 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3474 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3475 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:063476 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:103477 };
3478
3479 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3480 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073481 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:063482 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073483 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:103484
[email protected]49639fa2011-12-20 23:22:413485 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:103486
[email protected]262eec82013-03-19 21:01:363487 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503488 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a67a8152010-11-05 18:31:103489
[email protected]49639fa2011-12-20 23:22:413490 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7a67a8152010-11-05 18:31:103491 EXPECT_EQ(ERR_IO_PENDING, rv);
3492
3493 rv = callback1.WaitForResult();
3494 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
mmenke43758e62015-05-04 21:09:463495 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403496 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:103497 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403498 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:103499 NetLog::PHASE_NONE);
3500 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403501 entries, pos,
[email protected]7a67a8152010-11-05 18:31:103502 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3503 NetLog::PHASE_NONE);
3504}
[email protected]2df19bb2010-08-25 20:13:463505
mmenke2a1781d2015-10-07 19:25:333506// Test a proxy auth scheme that allows default credentials and a proxy server
3507// that uses non-persistent connections.
3508TEST_P(HttpNetworkTransactionTest,
3509 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
3510 HttpRequestInfo request;
3511 request.method = "GET";
3512 request.url = GURL("https://www.example.org/");
3513
3514 // Configure against proxy server "myproxy:70".
3515 session_deps_.proxy_service =
3516 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3517
3518 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3519 new HttpAuthHandlerMock::Factory());
3520 auth_handler_factory->set_do_init_from_challenge(true);
3521 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3522 mock_handler->set_allows_default_credentials(true);
3523 auth_handler_factory->AddMockHandler(mock_handler.release(),
3524 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483525 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333526
3527 // Add NetLog just so can verify load timing information gets a NetLog ID.
3528 NetLog net_log;
3529 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423530 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333531
3532 // Since we have proxy, should try to establish tunnel.
3533 MockWrite data_writes1[] = {
3534 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173535 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333536 "Proxy-Connection: keep-alive\r\n\r\n"),
3537 };
3538
3539 // The proxy responds to the connect with a 407, using a non-persistent
3540 // connection.
3541 MockRead data_reads1[] = {
3542 // No credentials.
3543 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3544 MockRead("Proxy-Authenticate: Mock\r\n"),
3545 MockRead("Proxy-Connection: close\r\n\r\n"),
3546 };
3547
3548 // Since the first connection couldn't be reused, need to establish another
3549 // once given credentials.
3550 MockWrite data_writes2[] = {
3551 // After calling trans->RestartWithAuth(), this is the request we should
3552 // be issuing -- the final header line contains the credentials.
3553 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173554 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333555 "Proxy-Connection: keep-alive\r\n"
3556 "Proxy-Authorization: auth_token\r\n\r\n"),
3557
3558 MockWrite("GET / HTTP/1.1\r\n"
3559 "Host: www.example.org\r\n"
3560 "Connection: keep-alive\r\n\r\n"),
3561 };
3562
3563 MockRead data_reads2[] = {
3564 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3565
3566 MockRead("HTTP/1.1 200 OK\r\n"),
3567 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3568 MockRead("Content-Length: 5\r\n\r\n"),
3569 MockRead(SYNCHRONOUS, "hello"),
3570 };
3571
3572 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3573 data_writes1, arraysize(data_writes1));
3574 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3575 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3576 data_writes2, arraysize(data_writes2));
3577 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3578 SSLSocketDataProvider ssl(ASYNC, OK);
3579 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3580
3581 scoped_ptr<HttpTransaction> trans(
3582 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3583
3584 TestCompletionCallback callback;
3585 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3586 EXPECT_EQ(OK, callback.GetResult(rv));
3587
3588 const HttpResponseInfo* response = trans->GetResponseInfo();
3589 ASSERT_TRUE(response);
3590 ASSERT_TRUE(response->headers);
3591 EXPECT_FALSE(response->headers->IsKeepAlive());
3592 EXPECT_EQ(407, response->headers->response_code());
3593 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3594 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3595 EXPECT_FALSE(response->auth_challenge.get());
3596
3597 LoadTimingInfo load_timing_info;
3598 // CONNECT requests and responses are handled at the connect job level, so
3599 // the transaction does not yet have a connection.
3600 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3601
3602 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3603 EXPECT_EQ(OK, callback.GetResult(rv));
3604 response = trans->GetResponseInfo();
3605 ASSERT_TRUE(response);
3606 ASSERT_TRUE(response->headers);
3607 EXPECT_TRUE(response->headers->IsKeepAlive());
3608 EXPECT_EQ(200, response->headers->response_code());
3609 EXPECT_EQ(5, response->headers->GetContentLength());
3610 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3611
3612 // The password prompt info should not be set.
3613 EXPECT_FALSE(response->auth_challenge);
3614
3615 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3616 TestLoadTimingNotReusedWithPac(load_timing_info,
3617 CONNECT_TIMING_HAS_SSL_TIMES);
3618
3619 trans.reset();
3620 session->CloseAllConnections();
3621}
3622
3623// Test a proxy auth scheme that allows default credentials and a proxy server
3624// that hangs up when credentials are initially sent.
3625TEST_P(HttpNetworkTransactionTest,
3626 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
3627 HttpRequestInfo request;
3628 request.method = "GET";
3629 request.url = GURL("https://www.example.org/");
3630
3631 // Configure against proxy server "myproxy:70".
3632 session_deps_.proxy_service =
3633 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3634
3635 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3636 new HttpAuthHandlerMock::Factory());
3637 auth_handler_factory->set_do_init_from_challenge(true);
3638 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3639 mock_handler->set_allows_default_credentials(true);
3640 auth_handler_factory->AddMockHandler(mock_handler.release(),
3641 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483642 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333643
3644 // Add NetLog just so can verify load timing information gets a NetLog ID.
3645 NetLog net_log;
3646 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423647 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333648
3649 // Should try to establish tunnel.
3650 MockWrite data_writes1[] = {
3651 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173652 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333653 "Proxy-Connection: keep-alive\r\n\r\n"),
3654
3655 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173656 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333657 "Proxy-Connection: keep-alive\r\n"
3658 "Proxy-Authorization: auth_token\r\n\r\n"),
3659 };
3660
3661 // The proxy responds to the connect with a 407, using a non-persistent
3662 // connection.
3663 MockRead data_reads1[] = {
3664 // No credentials.
3665 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3666 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3667 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3668 };
3669
3670 // Since the first connection was closed, need to establish another once given
3671 // credentials.
3672 MockWrite data_writes2[] = {
3673 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173674 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333675 "Proxy-Connection: keep-alive\r\n"
3676 "Proxy-Authorization: auth_token\r\n\r\n"),
3677
3678 MockWrite("GET / HTTP/1.1\r\n"
3679 "Host: www.example.org\r\n"
3680 "Connection: keep-alive\r\n\r\n"),
3681 };
3682
3683 MockRead data_reads2[] = {
3684 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3685
3686 MockRead("HTTP/1.1 200 OK\r\n"),
3687 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3688 MockRead("Content-Length: 5\r\n\r\n"),
3689 MockRead(SYNCHRONOUS, "hello"),
3690 };
3691
3692 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3693 data_writes1, arraysize(data_writes1));
3694 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3695 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3696 data_writes2, arraysize(data_writes2));
3697 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3698 SSLSocketDataProvider ssl(ASYNC, OK);
3699 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3700
3701 scoped_ptr<HttpTransaction> trans(
3702 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3703
3704 TestCompletionCallback callback;
3705 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3706 EXPECT_EQ(OK, callback.GetResult(rv));
3707
3708 const HttpResponseInfo* response = trans->GetResponseInfo();
3709 ASSERT_TRUE(response);
3710 ASSERT_TRUE(response->headers);
3711 EXPECT_TRUE(response->headers->IsKeepAlive());
3712 EXPECT_EQ(407, response->headers->response_code());
3713 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3714 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3715 EXPECT_FALSE(response->auth_challenge);
3716
3717 LoadTimingInfo load_timing_info;
3718 // CONNECT requests and responses are handled at the connect job level, so
3719 // the transaction does not yet have a connection.
3720 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3721
3722 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3723 EXPECT_EQ(OK, callback.GetResult(rv));
3724
3725 response = trans->GetResponseInfo();
3726 ASSERT_TRUE(response);
3727 ASSERT_TRUE(response->headers);
3728 EXPECT_TRUE(response->headers->IsKeepAlive());
3729 EXPECT_EQ(200, response->headers->response_code());
3730 EXPECT_EQ(5, response->headers->GetContentLength());
3731 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3732
3733 // The password prompt info should not be set.
3734 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3735
3736 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3737 TestLoadTimingNotReusedWithPac(load_timing_info,
3738 CONNECT_TIMING_HAS_SSL_TIMES);
3739
3740 trans.reset();
3741 session->CloseAllConnections();
3742}
3743
3744// Test a proxy auth scheme that allows default credentials and a proxy server
3745// that hangs up when credentials are initially sent, and hangs up again when
3746// they are retried.
3747TEST_P(HttpNetworkTransactionTest,
3748 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
3749 HttpRequestInfo request;
3750 request.method = "GET";
3751 request.url = GURL("https://www.example.org/");
3752
3753 // Configure against proxy server "myproxy:70".
3754 session_deps_.proxy_service =
3755 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3756
3757 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3758 new HttpAuthHandlerMock::Factory());
3759 auth_handler_factory->set_do_init_from_challenge(true);
3760 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3761 mock_handler->set_allows_default_credentials(true);
3762 auth_handler_factory->AddMockHandler(mock_handler.release(),
3763 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483764 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333765
3766 // Add NetLog just so can verify load timing information gets a NetLog ID.
3767 NetLog net_log;
3768 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423769 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333770
3771 // Should try to establish tunnel.
3772 MockWrite data_writes1[] = {
3773 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173774 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333775 "Proxy-Connection: keep-alive\r\n\r\n"),
3776
3777 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173778 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333779 "Proxy-Connection: keep-alive\r\n"
3780 "Proxy-Authorization: auth_token\r\n\r\n"),
3781 };
3782
3783 // The proxy responds to the connect with a 407, and then hangs up after the
3784 // second request is sent.
3785 MockRead data_reads1[] = {
3786 // No credentials.
3787 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3788 MockRead("Content-Length: 0\r\n"),
3789 MockRead("Proxy-Connection: keep-alive\r\n"),
3790 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3791 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3792 };
3793
3794 // HttpNetworkTransaction sees a reused connection that was closed with
3795 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
3796 // request.
3797 MockWrite data_writes2[] = {
3798 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173799 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333800 "Proxy-Connection: keep-alive\r\n\r\n"),
3801 };
3802
3803 // The proxy, having had more than enough of us, just hangs up.
3804 MockRead data_reads2[] = {
3805 // No credentials.
3806 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3807 };
3808
3809 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3810 data_writes1, arraysize(data_writes1));
3811 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3812 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3813 data_writes2, arraysize(data_writes2));
3814 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3815
3816 scoped_ptr<HttpTransaction> trans(
3817 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3818
3819 TestCompletionCallback callback;
3820 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3821 EXPECT_EQ(OK, callback.GetResult(rv));
3822
3823 const HttpResponseInfo* response = trans->GetResponseInfo();
3824 ASSERT_TRUE(response);
3825 ASSERT_TRUE(response->headers);
3826 EXPECT_TRUE(response->headers->IsKeepAlive());
3827 EXPECT_EQ(407, response->headers->response_code());
3828 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3829 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3830 EXPECT_FALSE(response->auth_challenge);
3831
3832 LoadTimingInfo load_timing_info;
3833 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3834
3835 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3836 EXPECT_EQ(ERR_EMPTY_RESPONSE, callback.GetResult(rv));
3837
3838 trans.reset();
3839 session->CloseAllConnections();
3840}
3841
3842// Test a proxy auth scheme that allows default credentials and a proxy server
3843// that hangs up when credentials are initially sent, and sends a challenge
3844// again they are retried.
3845TEST_P(HttpNetworkTransactionTest,
3846 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
3847 HttpRequestInfo request;
3848 request.method = "GET";
3849 request.url = GURL("https://www.example.org/");
3850
3851 // Configure against proxy server "myproxy:70".
3852 session_deps_.proxy_service =
3853 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3854
3855 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3856 new HttpAuthHandlerMock::Factory());
3857 auth_handler_factory->set_do_init_from_challenge(true);
3858 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3859 mock_handler->set_allows_default_credentials(true);
3860 auth_handler_factory->AddMockHandler(mock_handler.release(),
3861 HttpAuth::AUTH_PROXY);
3862 // Add another handler for the second challenge. It supports default
3863 // credentials, but they shouldn't be used, since they were already tried.
3864 mock_handler.reset(new HttpAuthHandlerMock());
3865 mock_handler->set_allows_default_credentials(true);
3866 auth_handler_factory->AddMockHandler(mock_handler.release(),
3867 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483868 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333869
3870 // Add NetLog just so can verify load timing information gets a NetLog ID.
3871 NetLog net_log;
3872 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423873 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333874
3875 // Should try to establish tunnel.
3876 MockWrite data_writes1[] = {
3877 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173878 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333879 "Proxy-Connection: keep-alive\r\n\r\n"),
3880 };
3881
3882 // The proxy responds to the connect with a 407, using a non-persistent
3883 // connection.
3884 MockRead data_reads1[] = {
3885 // No credentials.
3886 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3887 MockRead("Proxy-Authenticate: Mock\r\n"),
3888 MockRead("Proxy-Connection: close\r\n\r\n"),
3889 };
3890
3891 // Since the first connection was closed, need to establish another once given
3892 // credentials.
3893 MockWrite data_writes2[] = {
3894 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173895 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333896 "Proxy-Connection: keep-alive\r\n"
3897 "Proxy-Authorization: auth_token\r\n\r\n"),
3898 };
3899
3900 MockRead data_reads2[] = {
3901 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3902 MockRead("Proxy-Authenticate: Mock\r\n"),
3903 MockRead("Proxy-Connection: close\r\n\r\n"),
3904 };
3905
3906 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3907 data_writes1, arraysize(data_writes1));
3908 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3909 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3910 data_writes2, arraysize(data_writes2));
3911 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3912 SSLSocketDataProvider ssl(ASYNC, OK);
3913 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3914
3915 scoped_ptr<HttpTransaction> trans(
3916 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3917
3918 TestCompletionCallback callback;
3919 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3920 EXPECT_EQ(OK, callback.GetResult(rv));
3921
3922 const HttpResponseInfo* response = trans->GetResponseInfo();
3923 ASSERT_TRUE(response);
3924 ASSERT_TRUE(response->headers);
3925 EXPECT_EQ(407, response->headers->response_code());
3926 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3927 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3928 EXPECT_FALSE(response->auth_challenge);
3929
3930 LoadTimingInfo load_timing_info;
3931 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3932
3933 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3934 EXPECT_EQ(OK, callback.GetResult(rv));
3935 response = trans->GetResponseInfo();
3936 ASSERT_TRUE(response);
3937 ASSERT_TRUE(response->headers);
3938 EXPECT_EQ(407, response->headers->response_code());
3939 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3940 EXPECT_TRUE(response->auth_challenge);
3941
3942 trans.reset();
3943 session->CloseAllConnections();
3944}
3945
[email protected]029c83b62013-01-24 05:28:203946// Test the load timing for HTTPS requests with an HTTP proxy.
[email protected]23e482282013-06-14 16:08:023947TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:203948 HttpRequestInfo request1;
3949 request1.method = "GET";
bncce36dca22015-04-21 22:11:233950 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:203951
3952 HttpRequestInfo request2;
3953 request2.method = "GET";
bncce36dca22015-04-21 22:11:233954 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:203955
3956 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033957 session_deps_.proxy_service = ProxyService::CreateFixed("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:513958 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073959 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423960 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:203961
3962 // Since we have proxy, should try to establish tunnel.
3963 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:173964 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3965 "Host: www.example.org:443\r\n"
3966 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203967
rsleevidb16bb02015-11-12 23:47:173968 MockWrite("GET /1 HTTP/1.1\r\n"
3969 "Host: www.example.org\r\n"
3970 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203971
rsleevidb16bb02015-11-12 23:47:173972 MockWrite("GET /2 HTTP/1.1\r\n"
3973 "Host: www.example.org\r\n"
3974 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203975 };
3976
3977 // The proxy responds to the connect with a 407, using a persistent
3978 // connection.
3979 MockRead data_reads1[] = {
3980 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3981
3982 MockRead("HTTP/1.1 200 OK\r\n"),
3983 MockRead("Content-Length: 1\r\n\r\n"),
3984 MockRead(SYNCHRONOUS, "1"),
3985
3986 MockRead("HTTP/1.1 200 OK\r\n"),
3987 MockRead("Content-Length: 2\r\n\r\n"),
3988 MockRead(SYNCHRONOUS, "22"),
3989 };
3990
3991 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3992 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073993 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:203994 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073995 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:203996
3997 TestCompletionCallback callback1;
[email protected]262eec82013-03-19 21:01:363998 scoped_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:503999 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204000
4001 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
4002 EXPECT_EQ(ERR_IO_PENDING, rv);
4003
4004 rv = callback1.WaitForResult();
4005 EXPECT_EQ(OK, rv);
4006
4007 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
4008 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:504009 ASSERT_TRUE(response1->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204010 EXPECT_EQ(1, response1->headers->GetContentLength());
4011
4012 LoadTimingInfo load_timing_info1;
4013 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
4014 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
4015
4016 trans1.reset();
4017
4018 TestCompletionCallback callback2;
[email protected]262eec82013-03-19 21:01:364019 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504020 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204021
4022 rv = trans2->Start(&request2, callback2.callback(), log.bound());
4023 EXPECT_EQ(ERR_IO_PENDING, rv);
4024
4025 rv = callback2.WaitForResult();
4026 EXPECT_EQ(OK, rv);
4027
4028 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
4029 ASSERT_TRUE(response2 != NULL);
[email protected]90499482013-06-01 00:39:504030 ASSERT_TRUE(response2->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204031 EXPECT_EQ(2, response2->headers->GetContentLength());
4032
4033 LoadTimingInfo load_timing_info2;
4034 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4035 TestLoadTimingReused(load_timing_info2);
4036
4037 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
4038
4039 trans2.reset();
4040 session->CloseAllConnections();
4041}
4042
4043// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
[email protected]23e482282013-06-14 16:08:024044TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:204045 HttpRequestInfo request1;
4046 request1.method = "GET";
bncce36dca22015-04-21 22:11:234047 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:204048
4049 HttpRequestInfo request2;
4050 request2.method = "GET";
bncce36dca22015-04-21 22:11:234051 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:204052
4053 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034054 session_deps_.proxy_service =
4055 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:514056 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074057 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424058 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:204059
4060 // Since we have proxy, should try to establish tunnel.
4061 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174062 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4063 "Host: www.example.org:443\r\n"
4064 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204065
rsleevidb16bb02015-11-12 23:47:174066 MockWrite("GET /1 HTTP/1.1\r\n"
4067 "Host: www.example.org\r\n"
4068 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204069
rsleevidb16bb02015-11-12 23:47:174070 MockWrite("GET /2 HTTP/1.1\r\n"
4071 "Host: www.example.org\r\n"
4072 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204073 };
4074
4075 // The proxy responds to the connect with a 407, using a persistent
4076 // connection.
4077 MockRead data_reads1[] = {
4078 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4079
4080 MockRead("HTTP/1.1 200 OK\r\n"),
4081 MockRead("Content-Length: 1\r\n\r\n"),
4082 MockRead(SYNCHRONOUS, "1"),
4083
4084 MockRead("HTTP/1.1 200 OK\r\n"),
4085 MockRead("Content-Length: 2\r\n\r\n"),
4086 MockRead(SYNCHRONOUS, "22"),
4087 };
4088
4089 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4090 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074091 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:204092 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074093 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:204094
4095 TestCompletionCallback callback1;
[email protected]262eec82013-03-19 21:01:364096 scoped_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:504097 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204098
4099 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
4100 EXPECT_EQ(ERR_IO_PENDING, rv);
4101
4102 rv = callback1.WaitForResult();
4103 EXPECT_EQ(OK, rv);
4104
4105 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
4106 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:504107 ASSERT_TRUE(response1->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204108 EXPECT_EQ(1, response1->headers->GetContentLength());
4109
4110 LoadTimingInfo load_timing_info1;
4111 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
4112 TestLoadTimingNotReusedWithPac(load_timing_info1,
4113 CONNECT_TIMING_HAS_SSL_TIMES);
4114
4115 trans1.reset();
4116
4117 TestCompletionCallback callback2;
[email protected]262eec82013-03-19 21:01:364118 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504119 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204120
4121 rv = trans2->Start(&request2, callback2.callback(), log.bound());
4122 EXPECT_EQ(ERR_IO_PENDING, rv);
4123
4124 rv = callback2.WaitForResult();
4125 EXPECT_EQ(OK, rv);
4126
4127 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
4128 ASSERT_TRUE(response2 != NULL);
[email protected]90499482013-06-01 00:39:504129 ASSERT_TRUE(response2->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204130 EXPECT_EQ(2, response2->headers->GetContentLength());
4131
4132 LoadTimingInfo load_timing_info2;
4133 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4134 TestLoadTimingReusedWithPac(load_timing_info2);
4135
4136 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
4137
4138 trans2.reset();
4139 session->CloseAllConnections();
4140}
4141
[email protected]2df19bb2010-08-25 20:13:464142// Test a simple get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024143TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:274144 HttpRequestInfo request;
4145 request.method = "GET";
bncce36dca22015-04-21 22:11:234146 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274147
[email protected]2df19bb2010-08-25 20:13:464148 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034149 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514150 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074151 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424152 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:464153
[email protected]2df19bb2010-08-25 20:13:464154 // Since we have proxy, should use full url
4155 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234156 MockWrite(
4157 "GET http://www.example.org/ HTTP/1.1\r\n"
4158 "Host: www.example.org\r\n"
4159 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:464160 };
4161
4162 MockRead data_reads1[] = {
4163 MockRead("HTTP/1.1 200 OK\r\n"),
4164 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4165 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064166 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:464167 };
4168
4169 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4170 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074171 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064172 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074173 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:464174
[email protected]49639fa2011-12-20 23:22:414175 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:464176
[email protected]262eec82013-03-19 21:01:364177 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504178 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504179
[email protected]49639fa2011-12-20 23:22:414180 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:464181 EXPECT_EQ(ERR_IO_PENDING, rv);
4182
4183 rv = callback1.WaitForResult();
4184 EXPECT_EQ(OK, rv);
4185
[email protected]58e32bb2013-01-21 18:23:254186 LoadTimingInfo load_timing_info;
4187 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4188 TestLoadTimingNotReused(load_timing_info,
4189 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4190
[email protected]2df19bb2010-08-25 20:13:464191 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504192 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464193
4194 EXPECT_TRUE(response->headers->IsKeepAlive());
4195 EXPECT_EQ(200, response->headers->response_code());
4196 EXPECT_EQ(100, response->headers->GetContentLength());
4197 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4198
4199 // The password prompt info should not be set.
4200 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4201}
4202
[email protected]7642b5ae2010-09-01 20:55:174203// Test a SPDY get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024204TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:274205 HttpRequestInfo request;
4206 request.method = "GET";
bncce36dca22015-04-21 22:11:234207 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274208 request.load_flags = 0;
4209
[email protected]7642b5ae2010-09-01 20:55:174210 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034211 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514212 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074213 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424214 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:174215
bncce36dca22015-04-21 22:11:234216 // fetch http://www.example.org/ via SPDY
[email protected]cdf8f7e72013-05-23 10:56:464217 scoped_ptr<SpdyFrame> req(
4218 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rch8e6c6c42015-05-01 14:05:134219 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]7642b5ae2010-09-01 20:55:174220
[email protected]23e482282013-06-14 16:08:024221 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4222 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:174223 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134224 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:174225 };
4226
rch8e6c6c42015-05-01 14:05:134227 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4228 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074229 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:174230
[email protected]8ddf8322012-02-23 18:08:064231 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384232 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074233 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:174234
[email protected]49639fa2011-12-20 23:22:414235 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:174236
[email protected]262eec82013-03-19 21:01:364237 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504238 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504239
[email protected]49639fa2011-12-20 23:22:414240 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7642b5ae2010-09-01 20:55:174241 EXPECT_EQ(ERR_IO_PENDING, rv);
4242
4243 rv = callback1.WaitForResult();
4244 EXPECT_EQ(OK, rv);
4245
[email protected]58e32bb2013-01-21 18:23:254246 LoadTimingInfo load_timing_info;
4247 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4248 TestLoadTimingNotReused(load_timing_info,
4249 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4250
[email protected]7642b5ae2010-09-01 20:55:174251 const HttpResponseInfo* response = trans->GetResponseInfo();
4252 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504253 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024254 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:174255
4256 std::string response_data;
4257 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]448d4ca52012-03-04 04:12:234258 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:174259}
4260
[email protected]1c173852014-06-19 12:51:504261// Verifies that a session which races and wins against the owning transaction
4262// (completing prior to host resolution), doesn't fail the transaction.
4263// Regression test for crbug.com/334413.
4264TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
4265 HttpRequestInfo request;
4266 request.method = "GET";
bncce36dca22015-04-21 22:11:234267 request.url = GURL("http://www.example.org/");
[email protected]1c173852014-06-19 12:51:504268 request.load_flags = 0;
4269
4270 // Configure SPDY proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034271 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514272 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:504273 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424274 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:504275
bncce36dca22015-04-21 22:11:234276 // Fetch http://www.example.org/ through the SPDY proxy.
[email protected]1c173852014-06-19 12:51:504277 scoped_ptr<SpdyFrame> req(
4278 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rch8e6c6c42015-05-01 14:05:134279 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]1c173852014-06-19 12:51:504280
4281 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4282 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
4283 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134284 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:504285 };
4286
rch8e6c6c42015-05-01 14:05:134287 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4288 arraysize(spdy_writes));
[email protected]1c173852014-06-19 12:51:504289 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4290
4291 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384292 ssl.SetNextProto(GetProtocol());
[email protected]1c173852014-06-19 12:51:504293 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4294
4295 TestCompletionCallback callback1;
4296
4297 scoped_ptr<HttpTransaction> trans(
4298 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4299
4300 // Stall the hostname resolution begun by the transaction.
4301 session_deps_.host_resolver->set_synchronous_mode(false);
4302 session_deps_.host_resolver->set_ondemand_mode(true);
4303
4304 int rv = trans->Start(&request, callback1.callback(), log.bound());
4305 EXPECT_EQ(ERR_IO_PENDING, rv);
4306
4307 // Race a session to the proxy, which completes first.
4308 session_deps_.host_resolver->set_ondemand_mode(false);
4309 SpdySessionKey key(
4310 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
4311 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:424312 CreateSecureSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:504313
4314 // Unstall the resolution begun by the transaction.
4315 session_deps_.host_resolver->set_ondemand_mode(true);
4316 session_deps_.host_resolver->ResolveAllPending();
4317
4318 EXPECT_FALSE(callback1.have_result());
4319 rv = callback1.WaitForResult();
4320 EXPECT_EQ(OK, rv);
4321
4322 const HttpResponseInfo* response = trans->GetResponseInfo();
4323 ASSERT_TRUE(response != NULL);
4324 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024325 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:504326
4327 std::string response_data;
4328 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4329 EXPECT_EQ(kUploadData, response_data);
4330}
4331
[email protected]dc7bd1c52010-11-12 00:01:134332// Test a SPDY get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024333TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:274334 HttpRequestInfo request;
4335 request.method = "GET";
bncce36dca22015-04-21 22:11:234336 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274337 request.load_flags = 0;
4338
[email protected]79cb5c12011-09-12 13:12:044339 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034340 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:514341 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074342 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424343 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:134344
[email protected]dc7bd1c52010-11-12 00:01:134345 // The first request will be a bare GET, the second request will be a
4346 // GET with a Proxy-Authorization header.
[email protected]ff98d7f02012-03-22 21:44:194347 scoped_ptr<SpdyFrame> req_get(
[email protected]cdf8f7e72013-05-23 10:56:464348 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
rdsmithebb50aa2015-11-12 03:44:384349 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:134350 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464351 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:134352 };
[email protected]ff98d7f02012-03-22 21:44:194353 scoped_ptr<SpdyFrame> req_get_authorization(
[email protected]cdf8f7e72013-05-23 10:56:464354 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4355 arraysize(kExtraAuthorizationHeaders) / 2,
4356 false,
4357 3,
4358 LOWEST,
4359 false));
[email protected]dc7bd1c52010-11-12 00:01:134360 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134361 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:134362 };
4363
4364 // The first response is a 407 proxy authentication challenge, and the second
4365 // response will be a 200 response since the second request includes a valid
4366 // Authorization header.
4367 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464368 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:134369 };
[email protected]ff98d7f02012-03-22 21:44:194370 scoped_ptr<SpdyFrame> resp_authentication(
[email protected]23e482282013-06-14 16:08:024371 spdy_util_.ConstructSpdySynReplyError(
[email protected]dc7bd1c52010-11-12 00:01:134372 "407 Proxy Authentication Required",
4373 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
4374 1));
[email protected]ff98d7f02012-03-22 21:44:194375 scoped_ptr<SpdyFrame> body_authentication(
[email protected]23e482282013-06-14 16:08:024376 spdy_util_.ConstructSpdyBodyFrame(1, true));
4377 scoped_ptr<SpdyFrame> resp_data(
4378 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4379 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:134380 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134381 CreateMockRead(*resp_authentication, 1),
4382 CreateMockRead(*body_authentication, 2),
4383 CreateMockRead(*resp_data, 4),
4384 CreateMockRead(*body_data, 5),
4385 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:134386 };
4387
rch8e6c6c42015-05-01 14:05:134388 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4389 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074390 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:134391
[email protected]8ddf8322012-02-23 18:08:064392 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384393 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074394 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:134395
[email protected]49639fa2011-12-20 23:22:414396 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:134397
[email protected]262eec82013-03-19 21:01:364398 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504399 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]dc7bd1c52010-11-12 00:01:134400
[email protected]49639fa2011-12-20 23:22:414401 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]dc7bd1c52010-11-12 00:01:134402 EXPECT_EQ(ERR_IO_PENDING, rv);
4403
4404 rv = callback1.WaitForResult();
4405 EXPECT_EQ(OK, rv);
4406
4407 const HttpResponseInfo* const response = trans->GetResponseInfo();
4408
4409 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504410 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]dc7bd1c52010-11-12 00:01:134411 EXPECT_EQ(407, response->headers->response_code());
4412 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:044413 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]dc7bd1c52010-11-12 00:01:134414
[email protected]49639fa2011-12-20 23:22:414415 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:134416
[email protected]49639fa2011-12-20 23:22:414417 rv = trans->RestartWithAuth(
4418 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]dc7bd1c52010-11-12 00:01:134419 EXPECT_EQ(ERR_IO_PENDING, rv);
4420
4421 rv = callback2.WaitForResult();
4422 EXPECT_EQ(OK, rv);
4423
4424 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4425
4426 ASSERT_TRUE(response_restart != NULL);
[email protected]90499482013-06-01 00:39:504427 ASSERT_TRUE(response_restart->headers.get() != NULL);
[email protected]dc7bd1c52010-11-12 00:01:134428 EXPECT_EQ(200, response_restart->headers->response_code());
4429 // The password prompt info should not be set.
4430 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4431}
4432
[email protected]d9da5fe2010-10-13 22:37:164433// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
[email protected]23e482282013-06-14 16:08:024434TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:274435 HttpRequestInfo request;
4436 request.method = "GET";
bncce36dca22015-04-21 22:11:234437 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274438 request.load_flags = 0;
4439
[email protected]d9da5fe2010-10-13 22:37:164440 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034441 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514442 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074443 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424444 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164445
[email protected]262eec82013-03-19 21:01:364446 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504447 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164448
bncce36dca22015-04-21 22:11:234449 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344450 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234451 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
4452 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:164453
bncce36dca22015-04-21 22:11:234454 const char get[] =
4455 "GET / HTTP/1.1\r\n"
4456 "Host: www.example.org\r\n"
4457 "Connection: keep-alive\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:194458 scoped_ptr<SpdyFrame> wrapped_get(
[email protected]23e482282013-06-14 16:08:024459 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
4460 scoped_ptr<SpdyFrame> conn_resp(
4461 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:164462 const char resp[] = "HTTP/1.1 200 OK\r\n"
4463 "Content-Length: 10\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:194464 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:024465 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
[email protected]ff98d7f02012-03-22 21:44:194466 scoped_ptr<SpdyFrame> wrapped_body(
[email protected]23e482282013-06-14 16:08:024467 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
[email protected]ff98d7f02012-03-22 21:44:194468 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204469 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
[email protected]8d2f7012012-02-16 00:08:044470
4471 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134472 CreateMockWrite(*connect, 0),
4473 CreateMockWrite(*wrapped_get, 2),
4474 CreateMockWrite(*window_update, 6),
[email protected]8d2f7012012-02-16 00:08:044475 };
4476
[email protected]d9da5fe2010-10-13 22:37:164477 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134478 CreateMockRead(*conn_resp, 1, ASYNC),
4479 CreateMockRead(*wrapped_get_resp, 3, ASYNC),
4480 CreateMockRead(*wrapped_body, 4, ASYNC),
4481 CreateMockRead(*wrapped_body, 5, ASYNC),
4482 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:164483 };
4484
rch8e6c6c42015-05-01 14:05:134485 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4486 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074487 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164488
[email protected]8ddf8322012-02-23 18:08:064489 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384490 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074491 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064492 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074493 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164494
[email protected]49639fa2011-12-20 23:22:414495 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164496
[email protected]49639fa2011-12-20 23:22:414497 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164498 EXPECT_EQ(ERR_IO_PENDING, rv);
4499
4500 rv = callback1.WaitForResult();
rch8e6c6c42015-05-01 14:05:134501 ASSERT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:164502
[email protected]58e32bb2013-01-21 18:23:254503 LoadTimingInfo load_timing_info;
4504 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4505 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4506
[email protected]d9da5fe2010-10-13 22:37:164507 const HttpResponseInfo* response = trans->GetResponseInfo();
4508 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504509 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]d9da5fe2010-10-13 22:37:164510 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4511
4512 std::string response_data;
4513 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4514 EXPECT_EQ("1234567890", response_data);
4515}
4516
4517// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
[email protected]23e482282013-06-14 16:08:024518TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
rdsmithebb50aa2015-11-12 03:44:384519 SpdyTestUtil spdy_util_wrapped(GetProtocol(), GetDependenciesFromPriority());
4520
[email protected]cb9bf6ca2011-01-28 13:15:274521 HttpRequestInfo request;
4522 request.method = "GET";
bncce36dca22015-04-21 22:11:234523 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274524 request.load_flags = 0;
4525
[email protected]d9da5fe2010-10-13 22:37:164526 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034527 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514528 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074529 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424530 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164531
[email protected]262eec82013-03-19 21:01:364532 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504533 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164534
bncce36dca22015-04-21 22:11:234535 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344536 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234537 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
4538 // fetch https://www.example.org/ via SPDY
4539 const char kMyUrl[] = "https://www.example.org/";
[email protected]cdf8f7e72013-05-23 10:56:464540 scoped_ptr<SpdyFrame> get(
rdsmithebb50aa2015-11-12 03:44:384541 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
[email protected]23e482282013-06-14 16:08:024542 scoped_ptr<SpdyFrame> wrapped_get(
4543 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
4544 scoped_ptr<SpdyFrame> conn_resp(
4545 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4546 scoped_ptr<SpdyFrame> get_resp(
rdsmithebb50aa2015-11-12 03:44:384547 spdy_util_wrapped.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:194548 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:024549 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
rdsmithebb50aa2015-11-12 03:44:384550 scoped_ptr<SpdyFrame> body(spdy_util_wrapped.ConstructSpdyBodyFrame(1, true));
[email protected]23e482282013-06-14 16:08:024551 scoped_ptr<SpdyFrame> wrapped_body(
4552 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
[email protected]ff98d7f02012-03-22 21:44:194553 scoped_ptr<SpdyFrame> window_update_get_resp(
[email protected]c10b20852013-05-15 21:29:204554 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
[email protected]ff98d7f02012-03-22 21:44:194555 scoped_ptr<SpdyFrame> window_update_body(
[email protected]c10b20852013-05-15 21:29:204556 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
[email protected]8d2f7012012-02-16 00:08:044557
4558 MockWrite spdy_writes[] = {
rch32320842015-05-16 15:57:094559 CreateMockWrite(*connect, 0),
4560 CreateMockWrite(*wrapped_get, 2),
4561 CreateMockWrite(*window_update_get_resp, 6),
[email protected]8d2f7012012-02-16 00:08:044562 CreateMockWrite(*window_update_body, 7),
4563 };
4564
[email protected]d9da5fe2010-10-13 22:37:164565 MockRead spdy_reads[] = {
rch32320842015-05-16 15:57:094566 CreateMockRead(*conn_resp, 1, ASYNC),
4567 MockRead(ASYNC, ERR_IO_PENDING, 3),
rch8e6c6c42015-05-01 14:05:134568 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
rch32320842015-05-16 15:57:094569 CreateMockRead(*wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:134570 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:164571 };
4572
rch32320842015-05-16 15:57:094573 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4574 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074575 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164576
[email protected]8ddf8322012-02-23 18:08:064577 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384578 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074579 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064580 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384581 ssl2.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074582 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164583
[email protected]49639fa2011-12-20 23:22:414584 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164585
[email protected]49639fa2011-12-20 23:22:414586 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164587 EXPECT_EQ(ERR_IO_PENDING, rv);
4588
rch32320842015-05-16 15:57:094589 // Allow the SpdyProxyClientSocket's write callback to complete.
4590 base::MessageLoop::current()->RunUntilIdle();
4591 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:594592 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:164593 rv = callback1.WaitForResult();
4594 EXPECT_EQ(OK, rv);
4595
[email protected]58e32bb2013-01-21 18:23:254596 LoadTimingInfo load_timing_info;
4597 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4598 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4599
[email protected]d9da5fe2010-10-13 22:37:164600 const HttpResponseInfo* response = trans->GetResponseInfo();
4601 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504602 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024603 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:164604
4605 std::string response_data;
4606 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]448d4ca52012-03-04 04:12:234607 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:164608}
4609
4610// Test a SPDY CONNECT failure through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024611TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:274612 HttpRequestInfo request;
4613 request.method = "GET";
bncce36dca22015-04-21 22:11:234614 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274615 request.load_flags = 0;
4616
[email protected]d9da5fe2010-10-13 22:37:164617 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034618 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514619 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074620 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424621 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164622
[email protected]262eec82013-03-19 21:01:364623 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504624 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164625
bncce36dca22015-04-21 22:11:234626 // CONNECT to www.example.org:443 via SPDY
lgarrona91df87f2014-12-05 00:51:344627 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234628 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:204629 scoped_ptr<SpdyFrame> get(
4630 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:164631
4632 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:134633 CreateMockWrite(*connect, 0), CreateMockWrite(*get, 2),
[email protected]d9da5fe2010-10-13 22:37:164634 };
4635
[email protected]23e482282013-06-14 16:08:024636 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
4637 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:164638 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134639 CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:164640 };
4641
rch8e6c6c42015-05-01 14:05:134642 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4643 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074644 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164645
[email protected]8ddf8322012-02-23 18:08:064646 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384647 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074648 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064649 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384650 ssl2.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074651 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164652
[email protected]49639fa2011-12-20 23:22:414653 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164654
[email protected]49639fa2011-12-20 23:22:414655 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:164656 EXPECT_EQ(ERR_IO_PENDING, rv);
4657
4658 rv = callback1.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:174659 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]d9da5fe2010-10-13 22:37:164660
[email protected]4eddbc732012-08-09 05:40:174661 // TODO(ttuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:164662}
4663
[email protected]f6c63db52013-02-02 00:35:224664// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4665// HTTPS Proxy to different servers.
[email protected]23e482282013-06-14 16:08:024666TEST_P(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:224667 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
4668 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034669 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514670 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074671 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424672 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504673 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224674
4675 HttpRequestInfo request1;
4676 request1.method = "GET";
bncce36dca22015-04-21 22:11:234677 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224678 request1.load_flags = 0;
4679
4680 HttpRequestInfo request2;
4681 request2.method = "GET";
bncce36dca22015-04-21 22:11:234682 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:224683 request2.load_flags = 0;
4684
bncce36dca22015-04-21 22:11:234685 // CONNECT to www.example.org:443 via SPDY.
lgarrona91df87f2014-12-05 00:51:344686 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234687 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]23e482282013-06-14 16:08:024688 scoped_ptr<SpdyFrame> conn_resp1(
4689 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f6c63db52013-02-02 00:35:224690
bncce36dca22015-04-21 22:11:234691 // Fetch https://www.example.org/ via HTTP.
4692 const char get1[] =
4693 "GET / HTTP/1.1\r\n"
4694 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224695 "Connection: keep-alive\r\n\r\n";
4696 scoped_ptr<SpdyFrame> wrapped_get1(
[email protected]23e482282013-06-14 16:08:024697 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
[email protected]f6c63db52013-02-02 00:35:224698 const char resp1[] = "HTTP/1.1 200 OK\r\n"
4699 "Content-Length: 1\r\n\r\n";
4700 scoped_ptr<SpdyFrame> wrapped_get_resp1(
[email protected]23e482282013-06-14 16:08:024701 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
4702 scoped_ptr<SpdyFrame> wrapped_body1(
4703 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
[email protected]f6c63db52013-02-02 00:35:224704 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204705 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
[email protected]f6c63db52013-02-02 00:35:224706
bncce36dca22015-04-21 22:11:234707 // CONNECT to mail.example.org:443 via SPDY.
[email protected]745aa9c2014-06-27 02:21:294708 SpdyHeaderBlock connect2_block;
bnc7ecc1122015-09-28 13:22:494709 spdy_util_.MaybeAddVersionHeader(&connect2_block);
[email protected]745aa9c2014-06-27 02:21:294710 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
rdsmithebb50aa2015-11-12 03:44:384711 if (GetProtocol() == kProtoHTTP2) {
bnc6b996d532015-07-29 10:51:324712 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org:443";
4713 } else {
bnc6b996d532015-07-29 10:51:324714 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org";
bnc7ecc1122015-09-28 13:22:494715 connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443";
bnc6b996d532015-07-29 10:51:324716 }
[email protected]f6c63db52013-02-02 00:35:224717 scoped_ptr<SpdyFrame> connect2(
[email protected]745aa9c2014-06-27 02:21:294718 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
[email protected]601e03f12014-04-06 16:26:394719
[email protected]23e482282013-06-14 16:08:024720 scoped_ptr<SpdyFrame> conn_resp2(
4721 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]f6c63db52013-02-02 00:35:224722
bncce36dca22015-04-21 22:11:234723 // Fetch https://mail.example.org/ via HTTP.
4724 const char get2[] =
4725 "GET / HTTP/1.1\r\n"
4726 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224727 "Connection: keep-alive\r\n\r\n";
4728 scoped_ptr<SpdyFrame> wrapped_get2(
[email protected]23e482282013-06-14 16:08:024729 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
[email protected]f6c63db52013-02-02 00:35:224730 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4731 "Content-Length: 2\r\n\r\n";
4732 scoped_ptr<SpdyFrame> wrapped_get_resp2(
[email protected]23e482282013-06-14 16:08:024733 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
[email protected]f6c63db52013-02-02 00:35:224734 scoped_ptr<SpdyFrame> wrapped_body2(
[email protected]23e482282013-06-14 16:08:024735 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
[email protected]f6c63db52013-02-02 00:35:224736
4737 MockWrite spdy_writes[] = {
4738 CreateMockWrite(*connect1, 0),
4739 CreateMockWrite(*wrapped_get1, 2),
4740 CreateMockWrite(*connect2, 5),
4741 CreateMockWrite(*wrapped_get2, 7),
4742 };
4743
4744 MockRead spdy_reads[] = {
4745 CreateMockRead(*conn_resp1, 1, ASYNC),
4746 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4747 CreateMockRead(*wrapped_body1, 4, ASYNC),
4748 CreateMockRead(*conn_resp2, 6, ASYNC),
4749 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
4750 CreateMockRead(*wrapped_body2, 9, ASYNC),
4751 MockRead(ASYNC, 0, 10),
4752 };
4753
mmenke11eb5152015-06-09 14:50:504754 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4755 arraysize(spdy_writes));
4756 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224757
4758 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384759 ssl.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:504760 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224761 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504762 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:224763 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504764 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:224765
4766 TestCompletionCallback callback;
4767
[email protected]262eec82013-03-19 21:01:364768 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504769 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224770 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504771 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224772
4773 LoadTimingInfo load_timing_info;
4774 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4775 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4776
4777 const HttpResponseInfo* response = trans->GetResponseInfo();
4778 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504779 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]f6c63db52013-02-02 00:35:224780 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4781
4782 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:294783 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
mmenke11eb5152015-06-09 14:50:504784 rv = trans->Read(buf.get(), 256, callback.callback());
4785 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224786
[email protected]262eec82013-03-19 21:01:364787 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504788 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224789 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504790 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224791
4792 LoadTimingInfo load_timing_info2;
4793 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4794 // Even though the SPDY connection is reused, a new tunnelled connection has
4795 // to be created, so the socket's load timing looks like a fresh connection.
4796 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
4797
4798 // The requests should have different IDs, since they each are using their own
4799 // separate stream.
4800 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4801
mmenke11eb5152015-06-09 14:50:504802 rv = trans2->Read(buf.get(), 256, callback.callback());
4803 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224804}
4805
4806// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4807// HTTPS Proxy to the same server.
[email protected]23e482282013-06-14 16:08:024808TEST_P(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:224809 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
4810 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034811 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514812 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074813 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424814 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504815 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224816
4817 HttpRequestInfo request1;
4818 request1.method = "GET";
bncce36dca22015-04-21 22:11:234819 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224820 request1.load_flags = 0;
4821
4822 HttpRequestInfo request2;
4823 request2.method = "GET";
bncce36dca22015-04-21 22:11:234824 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:224825 request2.load_flags = 0;
4826
bncce36dca22015-04-21 22:11:234827 // CONNECT to www.example.org:443 via SPDY.
lgarrona91df87f2014-12-05 00:51:344828 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234829 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]23e482282013-06-14 16:08:024830 scoped_ptr<SpdyFrame> conn_resp1(
4831 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f6c63db52013-02-02 00:35:224832
bncce36dca22015-04-21 22:11:234833 // Fetch https://www.example.org/ via HTTP.
4834 const char get1[] =
4835 "GET / HTTP/1.1\r\n"
4836 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224837 "Connection: keep-alive\r\n\r\n";
4838 scoped_ptr<SpdyFrame> wrapped_get1(
[email protected]23e482282013-06-14 16:08:024839 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
[email protected]f6c63db52013-02-02 00:35:224840 const char resp1[] = "HTTP/1.1 200 OK\r\n"
4841 "Content-Length: 1\r\n\r\n";
4842 scoped_ptr<SpdyFrame> wrapped_get_resp1(
[email protected]23e482282013-06-14 16:08:024843 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
4844 scoped_ptr<SpdyFrame> wrapped_body1(
4845 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
[email protected]f6c63db52013-02-02 00:35:224846 scoped_ptr<SpdyFrame> window_update(
[email protected]c10b20852013-05-15 21:29:204847 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
[email protected]f6c63db52013-02-02 00:35:224848
bncce36dca22015-04-21 22:11:234849 // Fetch https://www.example.org/2 via HTTP.
4850 const char get2[] =
4851 "GET /2 HTTP/1.1\r\n"
4852 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224853 "Connection: keep-alive\r\n\r\n";
4854 scoped_ptr<SpdyFrame> wrapped_get2(
[email protected]23e482282013-06-14 16:08:024855 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
[email protected]f6c63db52013-02-02 00:35:224856 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4857 "Content-Length: 2\r\n\r\n";
4858 scoped_ptr<SpdyFrame> wrapped_get_resp2(
[email protected]23e482282013-06-14 16:08:024859 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
[email protected]f6c63db52013-02-02 00:35:224860 scoped_ptr<SpdyFrame> wrapped_body2(
[email protected]23e482282013-06-14 16:08:024861 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
[email protected]f6c63db52013-02-02 00:35:224862
4863 MockWrite spdy_writes[] = {
4864 CreateMockWrite(*connect1, 0),
4865 CreateMockWrite(*wrapped_get1, 2),
4866 CreateMockWrite(*wrapped_get2, 5),
4867 };
4868
4869 MockRead spdy_reads[] = {
4870 CreateMockRead(*conn_resp1, 1, ASYNC),
4871 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
4872 CreateMockRead(*wrapped_body1, 4, ASYNC),
4873 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
4874 CreateMockRead(*wrapped_body2, 7, ASYNC),
4875 MockRead(ASYNC, 0, 8),
4876 };
4877
mmenke11eb5152015-06-09 14:50:504878 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4879 arraysize(spdy_writes));
4880 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224881
4882 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384883 ssl.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:504884 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224885 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504886 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:224887
4888 TestCompletionCallback callback;
4889
[email protected]262eec82013-03-19 21:01:364890 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504891 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224892 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
4893 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f6c63db52013-02-02 00:35:224894
4895 rv = callback.WaitForResult();
4896 EXPECT_EQ(OK, rv);
4897
4898 LoadTimingInfo load_timing_info;
4899 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4900 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4901
4902 const HttpResponseInfo* response = trans->GetResponseInfo();
4903 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504904 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]f6c63db52013-02-02 00:35:224905 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4906
4907 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:294908 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
[email protected]90499482013-06-01 00:39:504909 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:224910 trans.reset();
4911
[email protected]262eec82013-03-19 21:01:364912 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504913 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224914 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
4915 EXPECT_EQ(ERR_IO_PENDING, rv);
4916
[email protected]f6c63db52013-02-02 00:35:224917 rv = callback.WaitForResult();
4918 EXPECT_EQ(OK, rv);
4919
4920 LoadTimingInfo load_timing_info2;
4921 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4922 TestLoadTimingReused(load_timing_info2);
4923
4924 // The requests should have the same ID.
4925 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4926
[email protected]90499482013-06-01 00:39:504927 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:224928}
4929
4930// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4931// Proxy to different servers.
mmenke11eb5152015-06-09 14:50:504932TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:224933 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034934 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514935 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074936 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424937 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504938 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224939
4940 HttpRequestInfo request1;
4941 request1.method = "GET";
bncce36dca22015-04-21 22:11:234942 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224943 request1.load_flags = 0;
4944
4945 HttpRequestInfo request2;
4946 request2.method = "GET";
bncce36dca22015-04-21 22:11:234947 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:224948 request2.load_flags = 0;
4949
bncce36dca22015-04-21 22:11:234950 // http://www.example.org/
[email protected]23e482282013-06-14 16:08:024951 scoped_ptr<SpdyHeaderBlock> headers(
bncce36dca22015-04-21 22:11:234952 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
[email protected]745aa9c2014-06-27 02:21:294953 scoped_ptr<SpdyFrame> get1(
4954 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]23e482282013-06-14 16:08:024955 scoped_ptr<SpdyFrame> get_resp1(
4956 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4957 scoped_ptr<SpdyFrame> body1(
4958 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
rdsmithebb50aa2015-11-12 03:44:384959 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:224960
bncce36dca22015-04-21 22:11:234961 // http://mail.example.org/
[email protected]23e482282013-06-14 16:08:024962 scoped_ptr<SpdyHeaderBlock> headers2(
bncce36dca22015-04-21 22:11:234963 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
[email protected]745aa9c2014-06-27 02:21:294964 scoped_ptr<SpdyFrame> get2(
4965 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
[email protected]23e482282013-06-14 16:08:024966 scoped_ptr<SpdyFrame> get_resp2(
4967 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4968 scoped_ptr<SpdyFrame> body2(
4969 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
[email protected]f6c63db52013-02-02 00:35:224970
4971 MockWrite spdy_writes[] = {
4972 CreateMockWrite(*get1, 0),
4973 CreateMockWrite(*get2, 3),
4974 };
4975
4976 MockRead spdy_reads[] = {
4977 CreateMockRead(*get_resp1, 1, ASYNC),
4978 CreateMockRead(*body1, 2, ASYNC),
4979 CreateMockRead(*get_resp2, 4, ASYNC),
4980 CreateMockRead(*body2, 5, ASYNC),
4981 MockRead(ASYNC, 0, 6),
4982 };
4983
mmenke11eb5152015-06-09 14:50:504984 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4985 arraysize(spdy_writes));
4986 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224987
4988 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384989 ssl.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:504990 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224991
4992 TestCompletionCallback callback;
4993
[email protected]262eec82013-03-19 21:01:364994 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504995 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224996 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:504997 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224998
4999 LoadTimingInfo load_timing_info;
5000 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5001 TestLoadTimingNotReused(load_timing_info,
5002 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5003
5004 const HttpResponseInfo* response = trans->GetResponseInfo();
5005 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:505006 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:025007 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:225008
5009 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:295010 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
mmenke11eb5152015-06-09 14:50:505011 rv = trans->Read(buf.get(), 256, callback.callback());
5012 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:225013 // Delete the first request, so the second one can reuse the socket.
5014 trans.reset();
5015
[email protected]262eec82013-03-19 21:01:365016 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:505017 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:225018 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
mmenke11eb5152015-06-09 14:50:505019 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:225020
5021 LoadTimingInfo load_timing_info2;
5022 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5023 TestLoadTimingReused(load_timing_info2);
5024
5025 // The requests should have the same ID.
5026 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
5027
mmenke11eb5152015-06-09 14:50:505028 rv = trans2->Read(buf.get(), 256, callback.callback());
5029 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:225030}
5031
[email protected]2df19bb2010-08-25 20:13:465032// Test the challenge-response-retry sequence through an HTTPS Proxy
[email protected]23e482282013-06-14 16:08:025033TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:465034 HttpRequestInfo request;
5035 request.method = "GET";
bncce36dca22015-04-21 22:11:235036 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:465037 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:295038 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2df19bb2010-08-25 20:13:465039
[email protected]79cb5c12011-09-12 13:12:045040 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035041 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:515042 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075043 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:425044 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275045
[email protected]2df19bb2010-08-25 20:13:465046 // Since we have proxy, should use full url
5047 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235048 MockWrite(
5049 "GET http://www.example.org/ HTTP/1.1\r\n"
5050 "Host: www.example.org\r\n"
5051 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465052
bncce36dca22015-04-21 22:11:235053 // After calling trans->RestartWithAuth(), this is the request we should
5054 // be issuing -- the final header line contains the credentials.
5055 MockWrite(
5056 "GET http://www.example.org/ HTTP/1.1\r\n"
5057 "Host: www.example.org\r\n"
5058 "Proxy-Connection: keep-alive\r\n"
5059 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465060 };
5061
5062 // The proxy responds to the GET with a 407, using a persistent
5063 // connection.
5064 MockRead data_reads1[] = {
5065 // No credentials.
5066 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5067 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5068 MockRead("Proxy-Connection: keep-alive\r\n"),
5069 MockRead("Content-Length: 0\r\n\r\n"),
5070
5071 MockRead("HTTP/1.1 200 OK\r\n"),
5072 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5073 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065074 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:465075 };
5076
5077 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5078 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:075079 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:065080 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075081 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:465082
[email protected]49639fa2011-12-20 23:22:415083 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:465084
[email protected]262eec82013-03-19 21:01:365085 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505086 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505087
[email protected]49639fa2011-12-20 23:22:415088 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:465089 EXPECT_EQ(ERR_IO_PENDING, rv);
5090
5091 rv = callback1.WaitForResult();
5092 EXPECT_EQ(OK, rv);
5093
[email protected]58e32bb2013-01-21 18:23:255094 LoadTimingInfo load_timing_info;
5095 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5096 TestLoadTimingNotReused(load_timing_info,
5097 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5098
[email protected]2df19bb2010-08-25 20:13:465099 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505100 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:505101 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]2df19bb2010-08-25 20:13:465102 EXPECT_EQ(407, response->headers->response_code());
5103 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:045104 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2df19bb2010-08-25 20:13:465105
[email protected]49639fa2011-12-20 23:22:415106 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:465107
[email protected]49639fa2011-12-20 23:22:415108 rv = trans->RestartWithAuth(
5109 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]2df19bb2010-08-25 20:13:465110 EXPECT_EQ(ERR_IO_PENDING, rv);
5111
5112 rv = callback2.WaitForResult();
5113 EXPECT_EQ(OK, rv);
5114
[email protected]58e32bb2013-01-21 18:23:255115 load_timing_info = LoadTimingInfo();
5116 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5117 // Retrying with HTTP AUTH is considered to be reusing a socket.
5118 TestLoadTimingReused(load_timing_info);
5119
[email protected]2df19bb2010-08-25 20:13:465120 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505121 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:465122
5123 EXPECT_TRUE(response->headers->IsKeepAlive());
5124 EXPECT_EQ(200, response->headers->response_code());
5125 EXPECT_EQ(100, response->headers->GetContentLength());
5126 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5127
5128 // The password prompt info should not be set.
5129 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5130}
5131
[email protected]23e482282013-06-14 16:08:025132void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:085133 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:425134 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:085135 request.method = "GET";
bncce36dca22015-04-21 22:11:235136 request.url = GURL("https://www.example.org/");
[email protected]c744cf22009-02-27 07:28:085137 request.load_flags = 0;
5138
[email protected]cb9bf6ca2011-01-28 13:15:275139 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035140 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:425141 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275142
[email protected]c744cf22009-02-27 07:28:085143 // Since we have proxy, should try to establish tunnel.
5144 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:175145 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5146 "Host: www.example.org:443\r\n"
5147 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:085148 };
5149
5150 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:235151 status, MockRead("Content-Length: 10\r\n\r\n"),
5152 // No response body because the test stops reading here.
5153 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:085154 };
5155
[email protected]31a2bfe2010-02-09 08:03:395156 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5157 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:075158 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:085159
[email protected]49639fa2011-12-20 23:22:415160 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:085161
[email protected]262eec82013-03-19 21:01:365162 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505163 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505164
[email protected]49639fa2011-12-20 23:22:415165 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425166 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:085167
5168 rv = callback.WaitForResult();
5169 EXPECT_EQ(expected_status, rv);
5170}
5171
[email protected]23e482282013-06-14 16:08:025172void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:235173 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:085174 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:425175 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:085176}
5177
[email protected]23e482282013-06-14 16:08:025178TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:085179 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
5180}
5181
[email protected]23e482282013-06-14 16:08:025182TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:085183 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
5184}
5185
[email protected]23e482282013-06-14 16:08:025186TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:085187 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
5188}
5189
[email protected]23e482282013-06-14 16:08:025190TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:085191 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
5192}
5193
[email protected]23e482282013-06-14 16:08:025194TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:085195 ConnectStatusHelper(
5196 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
5197}
5198
[email protected]23e482282013-06-14 16:08:025199TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:085200 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
5201}
5202
[email protected]23e482282013-06-14 16:08:025203TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:085204 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
5205}
5206
[email protected]23e482282013-06-14 16:08:025207TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:085208 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
5209}
5210
[email protected]23e482282013-06-14 16:08:025211TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:085212 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
5213}
5214
[email protected]23e482282013-06-14 16:08:025215TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:085216 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
5217}
5218
[email protected]23e482282013-06-14 16:08:025219TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:085220 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
5221}
5222
[email protected]23e482282013-06-14 16:08:025223TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:085224 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
5225}
5226
[email protected]23e482282013-06-14 16:08:025227TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:085228 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
5229}
5230
[email protected]23e482282013-06-14 16:08:025231TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:085232 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
5233}
5234
[email protected]23e482282013-06-14 16:08:025235TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:085236 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
5237}
5238
[email protected]23e482282013-06-14 16:08:025239TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:085240 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
5241}
5242
[email protected]0a17aab32014-04-24 03:32:375243TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
5244 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
5245}
5246
[email protected]23e482282013-06-14 16:08:025247TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:085248 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
5249}
5250
[email protected]23e482282013-06-14 16:08:025251TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:085252 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
5253}
5254
[email protected]23e482282013-06-14 16:08:025255TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:085256 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
5257}
5258
[email protected]23e482282013-06-14 16:08:025259TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:085260 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
5261}
5262
[email protected]23e482282013-06-14 16:08:025263TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:085264 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
5265}
5266
[email protected]23e482282013-06-14 16:08:025267TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:085268 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
5269}
5270
[email protected]23e482282013-06-14 16:08:025271TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:085272 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
5273}
5274
[email protected]23e482282013-06-14 16:08:025275TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:085276 ConnectStatusHelperWithExpectedStatus(
5277 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:545278 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:085279}
5280
[email protected]23e482282013-06-14 16:08:025281TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:085282 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
5283}
5284
[email protected]23e482282013-06-14 16:08:025285TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:085286 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
5287}
5288
[email protected]23e482282013-06-14 16:08:025289TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:085290 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
5291}
5292
[email protected]23e482282013-06-14 16:08:025293TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:085294 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
5295}
5296
[email protected]23e482282013-06-14 16:08:025297TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:085298 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
5299}
5300
[email protected]23e482282013-06-14 16:08:025301TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:085302 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
5303}
5304
[email protected]23e482282013-06-14 16:08:025305TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:085306 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
5307}
5308
[email protected]23e482282013-06-14 16:08:025309TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:085310 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
5311}
5312
[email protected]23e482282013-06-14 16:08:025313TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:085314 ConnectStatusHelper(
5315 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
5316}
5317
[email protected]23e482282013-06-14 16:08:025318TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:085319 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
5320}
5321
[email protected]23e482282013-06-14 16:08:025322TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:085323 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
5324}
5325
[email protected]23e482282013-06-14 16:08:025326TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:085327 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
5328}
5329
[email protected]23e482282013-06-14 16:08:025330TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:085331 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
5332}
5333
[email protected]23e482282013-06-14 16:08:025334TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:085335 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
5336}
5337
[email protected]23e482282013-06-14 16:08:025338TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:085339 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
5340}
5341
[email protected]23e482282013-06-14 16:08:025342TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:085343 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
5344}
5345
[email protected]038e9a32008-10-08 22:40:165346// Test the flow when both the proxy server AND origin server require
5347// authentication. Again, this uses basic auth for both since that is
5348// the simplest to mock.
[email protected]23e482282013-06-14 16:08:025349TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:275350 HttpRequestInfo request;
5351 request.method = "GET";
bncce36dca22015-04-21 22:11:235352 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:275353 request.load_flags = 0;
5354
[email protected]038e9a32008-10-08 22:40:165355 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035356 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:425357 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:075358
5359 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:415360 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]038e9a32008-10-08 22:40:165361
[email protected]f9ee6b52008-11-08 06:46:235362 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235363 MockWrite(
5364 "GET http://www.example.org/ HTTP/1.1\r\n"
5365 "Host: www.example.org\r\n"
5366 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:235367 };
5368
[email protected]038e9a32008-10-08 22:40:165369 MockRead data_reads1[] = {
5370 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
5371 // Give a couple authenticate options (only the middle one is actually
5372 // supported).
[email protected]22927ad2009-09-21 19:56:195373 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:165374 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5375 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
5376 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5377 // Large content-length -- won't matter, as connection will be reset.
5378 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065379 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:165380 };
5381
5382 // After calling trans->RestartWithAuth() the first time, this is the
5383 // request we should be issuing -- the final header line contains the
5384 // proxy's credentials.
5385 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:235386 MockWrite(
5387 "GET http://www.example.org/ HTTP/1.1\r\n"
5388 "Host: www.example.org\r\n"
5389 "Proxy-Connection: keep-alive\r\n"
5390 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:165391 };
5392
5393 // Now the proxy server lets the request pass through to origin server.
5394 // The origin server responds with a 401.
5395 MockRead data_reads2[] = {
5396 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5397 // Note: We are using the same realm-name as the proxy server. This is
5398 // completely valid, as realms are unique across hosts.
5399 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5400 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5401 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065402 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:165403 };
5404
5405 // After calling trans->RestartWithAuth() the second time, we should send
5406 // the credentials for both the proxy and origin server.
5407 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:235408 MockWrite(
5409 "GET http://www.example.org/ HTTP/1.1\r\n"
5410 "Host: www.example.org\r\n"
5411 "Proxy-Connection: keep-alive\r\n"
5412 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
5413 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:165414 };
5415
5416 // Lastly we get the desired content.
5417 MockRead data_reads3[] = {
5418 MockRead("HTTP/1.0 200 OK\r\n"),
5419 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5420 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065421 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:165422 };
5423
[email protected]31a2bfe2010-02-09 08:03:395424 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5425 data_writes1, arraysize(data_writes1));
5426 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5427 data_writes2, arraysize(data_writes2));
5428 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5429 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:075430 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5431 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5432 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:165433
[email protected]49639fa2011-12-20 23:22:415434 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:165435
[email protected]49639fa2011-12-20 23:22:415436 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425437 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165438
5439 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425440 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165441
[email protected]1c773ea12009-04-28 19:58:425442 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505443 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045444 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:165445
[email protected]49639fa2011-12-20 23:22:415446 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:165447
[email protected]49639fa2011-12-20 23:22:415448 rv = trans->RestartWithAuth(
5449 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:425450 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165451
5452 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425453 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165454
5455 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505456 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045457 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:165458
[email protected]49639fa2011-12-20 23:22:415459 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:165460
[email protected]49639fa2011-12-20 23:22:415461 rv = trans->RestartWithAuth(
5462 AuthCredentials(kFoo2, kBar2), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425463 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:165464
5465 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425466 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:165467
5468 response = trans->GetResponseInfo();
5469 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5470 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:165471}
[email protected]4ddaf2502008-10-23 18:26:195472
[email protected]ea9dc9a2009-09-05 00:43:325473// For the NTLM implementation using SSPI, we skip the NTLM tests since we
5474// can't hook into its internals to cause it to generate predictable NTLM
5475// authorization headers.
5476#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:295477// The NTLM authentication unit tests were generated by capturing the HTTP
5478// requests and responses using Fiddler 2 and inspecting the generated random
5479// bytes in the debugger.
5480
5481// Enter the correct password and authenticate successfully.
[email protected]23e482282013-06-14 16:08:025482TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:425483 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:245484 request.method = "GET";
5485 request.url = GURL("http://172.22.68.17/kids/login.aspx");
[email protected]2217aa22013-10-11 03:03:545486
5487 // Ensure load is not disrupted by flags which suppress behaviour specific
5488 // to other auth schemes.
5489 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:245490
[email protected]cb9bf6ca2011-01-28 13:15:275491 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
5492 MockGetHostName);
mmenkee65e7af2015-10-13 17:16:425493 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275494
[email protected]3f918782009-02-28 01:29:245495 MockWrite data_writes1[] = {
5496 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5497 "Host: 172.22.68.17\r\n"
5498 "Connection: keep-alive\r\n\r\n"),
5499 };
5500
5501 MockRead data_reads1[] = {
5502 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:045503 // Negotiate and NTLM are often requested together. However, we only want
5504 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
5505 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:245506 MockRead("WWW-Authenticate: NTLM\r\n"),
5507 MockRead("Connection: close\r\n"),
5508 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365509 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245510 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065511 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:245512 };
5513
5514 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:225515 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:245516 // request we should be issuing -- the final header line contains a Type
5517 // 1 message.
5518 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5519 "Host: 172.22.68.17\r\n"
5520 "Connection: keep-alive\r\n"
5521 "Authorization: NTLM "
5522 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5523
5524 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5525 // (the credentials for the origin server). The second request continues
5526 // on the same connection.
5527 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5528 "Host: 172.22.68.17\r\n"
5529 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:295530 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5531 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5532 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
5533 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
5534 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245535 };
5536
5537 MockRead data_reads2[] = {
5538 // The origin server responds with a Type 2 message.
5539 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5540 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:295541 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:245542 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5543 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5544 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5545 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5546 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5547 "BtAAAAAAA=\r\n"),
5548 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365549 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245550 MockRead("You are not authorized to view this page\r\n"),
5551
5552 // Lastly we get the desired content.
5553 MockRead("HTTP/1.1 200 OK\r\n"),
5554 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
5555 MockRead("Content-Length: 13\r\n\r\n"),
5556 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:065557 MockRead(SYNCHRONOUS, OK),
[email protected]3f918782009-02-28 01:29:245558 };
5559
[email protected]31a2bfe2010-02-09 08:03:395560 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5561 data_writes1, arraysize(data_writes1));
5562 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5563 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:075564 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5565 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:245566
[email protected]49639fa2011-12-20 23:22:415567 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:245568
[email protected]262eec82013-03-19 21:01:365569 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505570 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505571
[email protected]49639fa2011-12-20 23:22:415572 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425573 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:245574
5575 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425576 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:245577
[email protected]0757e7702009-03-27 04:00:225578 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5579
[email protected]1c773ea12009-04-28 19:58:425580 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:045581 ASSERT_FALSE(response == NULL);
5582 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]3f918782009-02-28 01:29:245583
[email protected]49639fa2011-12-20 23:22:415584 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:255585
[email protected]f3cf9802011-10-28 18:44:585586 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:415587 callback2.callback());
[email protected]10af5fe72011-01-31 16:17:255588 EXPECT_EQ(ERR_IO_PENDING, rv);
5589
5590 rv = callback2.WaitForResult();
5591 EXPECT_EQ(OK, rv);
5592
5593 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5594
5595 response = trans->GetResponseInfo();
5596 ASSERT_TRUE(response != NULL);
[email protected]10af5fe72011-01-31 16:17:255597 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5598
[email protected]49639fa2011-12-20 23:22:415599 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:245600
[email protected]49639fa2011-12-20 23:22:415601 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425602 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:245603
[email protected]0757e7702009-03-27 04:00:225604 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425605 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:245606
5607 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505608 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:245609 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5610 EXPECT_EQ(13, response->headers->GetContentLength());
5611}
5612
[email protected]385a4672009-03-11 22:21:295613// Enter a wrong password, and then the correct one.
[email protected]23e482282013-06-14 16:08:025614TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:425615 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:295616 request.method = "GET";
5617 request.url = GURL("http://172.22.68.17/kids/login.aspx");
5618 request.load_flags = 0;
5619
[email protected]cb9bf6ca2011-01-28 13:15:275620 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
5621 MockGetHostName);
mmenkee65e7af2015-10-13 17:16:425622 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275623
[email protected]385a4672009-03-11 22:21:295624 MockWrite data_writes1[] = {
5625 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5626 "Host: 172.22.68.17\r\n"
5627 "Connection: keep-alive\r\n\r\n"),
5628 };
5629
5630 MockRead data_reads1[] = {
5631 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:045632 // Negotiate and NTLM are often requested together. However, we only want
5633 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
5634 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:295635 MockRead("WWW-Authenticate: NTLM\r\n"),
5636 MockRead("Connection: close\r\n"),
5637 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365638 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295639 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065640 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:295641 };
5642
5643 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:225644 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:295645 // request we should be issuing -- the final header line contains a Type
5646 // 1 message.
5647 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5648 "Host: 172.22.68.17\r\n"
5649 "Connection: keep-alive\r\n"
5650 "Authorization: NTLM "
5651 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5652
5653 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5654 // (the credentials for the origin server). The second request continues
5655 // on the same connection.
5656 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5657 "Host: 172.22.68.17\r\n"
5658 "Connection: keep-alive\r\n"
5659 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5660 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5661 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
5662 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
5663 "4Ww7b7E=\r\n\r\n"),
5664 };
5665
5666 MockRead data_reads2[] = {
5667 // The origin server responds with a Type 2 message.
5668 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5669 MockRead("WWW-Authenticate: NTLM "
5670 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
5671 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5672 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5673 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5674 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5675 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5676 "BtAAAAAAA=\r\n"),
5677 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365678 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295679 MockRead("You are not authorized to view this page\r\n"),
5680
5681 // Wrong password.
5682 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:295683 MockRead("WWW-Authenticate: NTLM\r\n"),
5684 MockRead("Connection: close\r\n"),
5685 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365686 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295687 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065688 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:295689 };
5690
5691 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:225692 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:295693 // request we should be issuing -- the final header line contains a Type
5694 // 1 message.
5695 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5696 "Host: 172.22.68.17\r\n"
5697 "Connection: keep-alive\r\n"
5698 "Authorization: NTLM "
5699 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5700
5701 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5702 // (the credentials for the origin server). The second request continues
5703 // on the same connection.
5704 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5705 "Host: 172.22.68.17\r\n"
5706 "Connection: keep-alive\r\n"
5707 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5708 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5709 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
5710 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
5711 "+4MUm7c=\r\n\r\n"),
5712 };
5713
5714 MockRead data_reads3[] = {
5715 // The origin server responds with a Type 2 message.
5716 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5717 MockRead("WWW-Authenticate: NTLM "
5718 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
5719 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5720 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5721 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5722 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5723 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5724 "BtAAAAAAA=\r\n"),
5725 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365726 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295727 MockRead("You are not authorized to view this page\r\n"),
5728
5729 // Lastly we get the desired content.
5730 MockRead("HTTP/1.1 200 OK\r\n"),
5731 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
5732 MockRead("Content-Length: 13\r\n\r\n"),
5733 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:065734 MockRead(SYNCHRONOUS, OK),
[email protected]385a4672009-03-11 22:21:295735 };
5736
[email protected]31a2bfe2010-02-09 08:03:395737 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5738 data_writes1, arraysize(data_writes1));
5739 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5740 data_writes2, arraysize(data_writes2));
5741 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5742 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:075743 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5744 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5745 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:295746
[email protected]49639fa2011-12-20 23:22:415747 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:295748
[email protected]262eec82013-03-19 21:01:365749 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505750 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505751
[email protected]49639fa2011-12-20 23:22:415752 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425753 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:295754
5755 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425756 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:295757
[email protected]0757e7702009-03-27 04:00:225758 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:295759
[email protected]1c773ea12009-04-28 19:58:425760 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505761 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045762 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]385a4672009-03-11 22:21:295763
[email protected]49639fa2011-12-20 23:22:415764 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:295765
[email protected]0757e7702009-03-27 04:00:225766 // Enter the wrong password.
[email protected]f3cf9802011-10-28 18:44:585767 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
[email protected]49639fa2011-12-20 23:22:415768 callback2.callback());
[email protected]1c773ea12009-04-28 19:58:425769 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:295770
[email protected]10af5fe72011-01-31 16:17:255771 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425772 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:295773
[email protected]0757e7702009-03-27 04:00:225774 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:415775 TestCompletionCallback callback3;
5776 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:425777 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:255778 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425779 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:225780 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5781
5782 response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:045783 ASSERT_FALSE(response == NULL);
5784 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]0757e7702009-03-27 04:00:225785
[email protected]49639fa2011-12-20 23:22:415786 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:225787
5788 // Now enter the right password.
[email protected]f3cf9802011-10-28 18:44:585789 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:415790 callback4.callback());
[email protected]10af5fe72011-01-31 16:17:255791 EXPECT_EQ(ERR_IO_PENDING, rv);
5792
5793 rv = callback4.WaitForResult();
5794 EXPECT_EQ(OK, rv);
5795
5796 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5797
[email protected]49639fa2011-12-20 23:22:415798 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:255799
5800 // One more roundtrip
[email protected]49639fa2011-12-20 23:22:415801 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
[email protected]1c773ea12009-04-28 19:58:425802 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:225803
5804 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425805 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:225806
[email protected]385a4672009-03-11 22:21:295807 response = trans->GetResponseInfo();
5808 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5809 EXPECT_EQ(13, response->headers->GetContentLength());
5810}
[email protected]ea9dc9a2009-09-05 00:43:325811#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:295812
[email protected]4ddaf2502008-10-23 18:26:195813// Test reading a server response which has only headers, and no body.
5814// After some maximum number of bytes is consumed, the transaction should
5815// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
[email protected]23e482282013-06-14 16:08:025816TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:425817 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:195818 request.method = "GET";
bncce36dca22015-04-21 22:11:235819 request.url = GURL("http://www.example.org/");
[email protected]4ddaf2502008-10-23 18:26:195820 request.load_flags = 0;
5821
mmenkee65e7af2015-10-13 17:16:425822 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275823 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:415824 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:275825
[email protected]b75b7b2f2009-10-06 00:54:535826 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:435827 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:535828 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:195829
5830 MockRead data_reads[] = {
5831 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:065832 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:195833 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:065834 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:195835 };
[email protected]31a2bfe2010-02-09 08:03:395836 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:075837 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:195838
[email protected]49639fa2011-12-20 23:22:415839 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:195840
[email protected]49639fa2011-12-20 23:22:415841 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425842 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:195843
5844 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425845 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:195846}
[email protected]f4e426b2008-11-05 00:24:495847
5848// Make sure that we don't try to reuse a TCPClientSocket when failing to
5849// establish tunnel.
5850// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]23e482282013-06-14 16:08:025851TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:235852 DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:275853 HttpRequestInfo request;
5854 request.method = "GET";
bncce36dca22015-04-21 22:11:235855 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:275856 request.load_flags = 0;
5857
[email protected]f4e426b2008-11-05 00:24:495858 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035859 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]db8f44c2008-12-13 04:52:015860
mmenkee65e7af2015-10-13 17:16:425861 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:495862
[email protected]262eec82013-03-19 21:01:365863 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505864 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f4e426b2008-11-05 00:24:495865
[email protected]f4e426b2008-11-05 00:24:495866 // Since we have proxy, should try to establish tunnel.
5867 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175868 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5869 "Host: www.example.org:443\r\n"
5870 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:495871 };
5872
[email protected]77848d12008-11-14 00:00:225873 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:495874 // connection. Usually a proxy would return 501 (not implemented),
5875 // or 200 (tunnel established).
5876 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:235877 MockRead("HTTP/1.1 404 Not Found\r\n"),
5878 MockRead("Content-Length: 10\r\n\r\n"),
5879 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:495880 };
5881
[email protected]31a2bfe2010-02-09 08:03:395882 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5883 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:075884 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:495885
[email protected]49639fa2011-12-20 23:22:415886 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:495887
[email protected]49639fa2011-12-20 23:22:415888 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425889 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:495890
5891 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425892 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:495893
[email protected]b4404c02009-04-10 16:38:525894 // Empty the current queue. This is necessary because idle sockets are
5895 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345896 base::MessageLoop::current()->RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:525897
[email protected]f4e426b2008-11-05 00:24:495898 // We now check to make sure the TCPClientSocket was not added back to
5899 // the pool.
[email protected]90499482013-06-01 00:39:505900 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:495901 trans.reset();
[email protected]2da659e2013-05-23 20:51:345902 base::MessageLoop::current()->RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:495903 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:505904 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:495905}
[email protected]372d34a2008-11-05 21:30:515906
[email protected]1b157c02009-04-21 01:55:405907// Make sure that we recycle a socket after reading all of the response body.
[email protected]23e482282013-06-14 16:08:025908TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:425909 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:405910 request.method = "GET";
bncce36dca22015-04-21 22:11:235911 request.url = GURL("http://www.example.org/");
[email protected]1b157c02009-04-21 01:55:405912 request.load_flags = 0;
5913
mmenkee65e7af2015-10-13 17:16:425914 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275915
[email protected]262eec82013-03-19 21:01:365916 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505917 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:275918
[email protected]1b157c02009-04-21 01:55:405919 MockRead data_reads[] = {
5920 // A part of the response body is received with the response headers.
5921 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5922 // The rest of the response body is received in two parts.
5923 MockRead("lo"),
5924 MockRead(" world"),
5925 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:065926 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:405927 };
5928
[email protected]31a2bfe2010-02-09 08:03:395929 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:075930 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:405931
[email protected]49639fa2011-12-20 23:22:415932 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:405933
[email protected]49639fa2011-12-20 23:22:415934 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425935 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:405936
5937 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:425938 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:405939
[email protected]1c773ea12009-04-28 19:58:425940 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505941 ASSERT_TRUE(response != NULL);
[email protected]1b157c02009-04-21 01:55:405942
[email protected]90499482013-06-01 00:39:505943 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]1b157c02009-04-21 01:55:405944 std::string status_line = response->headers->GetStatusLine();
5945 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
5946
[email protected]90499482013-06-01 00:39:505947 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:405948
5949 std::string response_data;
5950 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:425951 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:405952 EXPECT_EQ("hello world", response_data);
5953
5954 // Empty the current queue. This is necessary because idle sockets are
5955 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:345956 base::MessageLoop::current()->RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:405957
5958 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:505959 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:405960}
5961
[email protected]76a505b2010-08-25 06:23:005962// Make sure that we recycle a SSL socket after reading all of the response
5963// body.
[email protected]23e482282013-06-14 16:08:025964TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:005965 HttpRequestInfo request;
5966 request.method = "GET";
bncce36dca22015-04-21 22:11:235967 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:005968 request.load_flags = 0;
5969
5970 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:235971 MockWrite(
5972 "GET / HTTP/1.1\r\n"
5973 "Host: www.example.org\r\n"
5974 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:005975 };
5976
5977 MockRead data_reads[] = {
5978 MockRead("HTTP/1.1 200 OK\r\n"),
5979 MockRead("Content-Length: 11\r\n\r\n"),
5980 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:065981 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:005982 };
5983
[email protected]8ddf8322012-02-23 18:08:065984 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075985 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:005986
5987 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5988 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:075989 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:005990
[email protected]49639fa2011-12-20 23:22:415991 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:005992
mmenkee65e7af2015-10-13 17:16:425993 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:365994 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505995 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:005996
[email protected]49639fa2011-12-20 23:22:415997 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:005998
5999 EXPECT_EQ(ERR_IO_PENDING, rv);
6000 EXPECT_EQ(OK, callback.WaitForResult());
6001
6002 const HttpResponseInfo* response = trans->GetResponseInfo();
6003 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:506004 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:006005 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6006
[email protected]90499482013-06-01 00:39:506007 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006008
6009 std::string response_data;
6010 rv = ReadTransaction(trans.get(), &response_data);
6011 EXPECT_EQ(OK, rv);
6012 EXPECT_EQ("hello world", response_data);
6013
6014 // Empty the current queue. This is necessary because idle sockets are
6015 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:346016 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:006017
6018 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506019 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006020}
6021
6022// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
6023// from the pool and make sure that we recover okay.
[email protected]23e482282013-06-14 16:08:026024TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:006025 HttpRequestInfo request;
6026 request.method = "GET";
bncce36dca22015-04-21 22:11:236027 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:006028 request.load_flags = 0;
6029
6030 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:236031 MockWrite(
6032 "GET / HTTP/1.1\r\n"
6033 "Host: www.example.org\r\n"
6034 "Connection: keep-alive\r\n\r\n"),
6035 MockWrite(
6036 "GET / HTTP/1.1\r\n"
6037 "Host: www.example.org\r\n"
6038 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:006039 };
6040
6041 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:426042 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
6043 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:006044
[email protected]8ddf8322012-02-23 18:08:066045 SSLSocketDataProvider ssl(ASYNC, OK);
6046 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076047 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6048 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:006049
6050 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6051 data_writes, arraysize(data_writes));
6052 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
6053 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:076054 session_deps_.socket_factory->AddSocketDataProvider(&data);
6055 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:006056
[email protected]49639fa2011-12-20 23:22:416057 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:006058
mmenkee65e7af2015-10-13 17:16:426059 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:366060 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506061 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:006062
[email protected]49639fa2011-12-20 23:22:416063 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:006064
6065 EXPECT_EQ(ERR_IO_PENDING, rv);
6066 EXPECT_EQ(OK, callback.WaitForResult());
6067
6068 const HttpResponseInfo* response = trans->GetResponseInfo();
6069 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:506070 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:006071 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6072
[email protected]90499482013-06-01 00:39:506073 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006074
6075 std::string response_data;
6076 rv = ReadTransaction(trans.get(), &response_data);
6077 EXPECT_EQ(OK, rv);
6078 EXPECT_EQ("hello world", response_data);
6079
6080 // Empty the current queue. This is necessary because idle sockets are
6081 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:346082 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:006083
6084 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506085 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006086
6087 // Now start the second transaction, which should reuse the previous socket.
6088
[email protected]90499482013-06-01 00:39:506089 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:006090
[email protected]49639fa2011-12-20 23:22:416091 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:006092
6093 EXPECT_EQ(ERR_IO_PENDING, rv);
6094 EXPECT_EQ(OK, callback.WaitForResult());
6095
6096 response = trans->GetResponseInfo();
6097 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:506098 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]76a505b2010-08-25 06:23:006099 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6100
[email protected]90499482013-06-01 00:39:506101 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006102
6103 rv = ReadTransaction(trans.get(), &response_data);
6104 EXPECT_EQ(OK, rv);
6105 EXPECT_EQ("hello world", response_data);
6106
6107 // Empty the current queue. This is necessary because idle sockets are
6108 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:346109 base::MessageLoop::current()->RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:006110
6111 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506112 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006113}
6114
[email protected]b4404c02009-04-10 16:38:526115// Make sure that we recycle a socket after a zero-length response.
6116// http://crbug.com/9880
[email protected]23e482282013-06-14 16:08:026117TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:426118 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:526119 request.method = "GET";
bncce36dca22015-04-21 22:11:236120 request.url = GURL(
6121 "http://www.example.org/csi?v=3&s=web&action=&"
6122 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
6123 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
6124 "rt=prt.2642,ol.2649,xjs.2951");
[email protected]b4404c02009-04-10 16:38:526125 request.load_flags = 0;
6126
mmenkee65e7af2015-10-13 17:16:426127 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276128
[email protected]b4404c02009-04-10 16:38:526129 MockRead data_reads[] = {
6130 MockRead("HTTP/1.1 204 No Content\r\n"
6131 "Content-Length: 0\r\n"
6132 "Content-Type: text/html\r\n\r\n"),
6133 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:066134 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:526135 };
6136
[email protected]31a2bfe2010-02-09 08:03:396137 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:076138 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:526139
mmenkecc2298e2015-12-07 18:20:186140 // Transaction must be created after the MockReads, so it's destroyed before
6141 // them.
6142 scoped_ptr<HttpTransaction> trans(
6143 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6144
[email protected]49639fa2011-12-20 23:22:416145 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:526146
[email protected]49639fa2011-12-20 23:22:416147 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426148 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:526149
6150 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426151 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:526152
[email protected]1c773ea12009-04-28 19:58:426153 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506154 ASSERT_TRUE(response != NULL);
[email protected]b4404c02009-04-10 16:38:526155
[email protected]90499482013-06-01 00:39:506156 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]b4404c02009-04-10 16:38:526157 std::string status_line = response->headers->GetStatusLine();
6158 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
6159
[email protected]90499482013-06-01 00:39:506160 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:526161
6162 std::string response_data;
6163 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:426164 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:526165 EXPECT_EQ("", response_data);
6166
6167 // Empty the current queue. This is necessary because idle sockets are
6168 // added to the connection pool asynchronously with a PostTask.
[email protected]2da659e2013-05-23 20:51:346169 base::MessageLoop::current()->RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:526170
6171 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506172 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:526173}
6174
[email protected]23e482282013-06-14 16:08:026175TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
olli.raula6df48b2a2015-11-26 07:40:226176 std::vector<scoped_ptr<UploadElementReader>> element_readers;
6177 element_readers.push_back(
6178 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
6179 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:276180
[email protected]1c773ea12009-04-28 19:58:426181 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:516182 // Transaction 1: a GET request that succeeds. The socket is recycled
6183 // after use.
6184 request[0].method = "GET";
6185 request[0].url = GURL("http://www.google.com/");
6186 request[0].load_flags = 0;
6187 // Transaction 2: a POST request. Reuses the socket kept alive from
6188 // transaction 1. The first attempts fails when writing the POST data.
6189 // This causes the transaction to retry with a new socket. The second
6190 // attempt succeeds.
6191 request[1].method = "POST";
6192 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:276193 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:516194 request[1].load_flags = 0;
6195
mmenkee65e7af2015-10-13 17:16:426196 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:516197
6198 // The first socket is used for transaction 1 and the first attempt of
6199 // transaction 2.
6200
6201 // The response of transaction 1.
6202 MockRead data_reads1[] = {
6203 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
6204 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066205 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:516206 };
6207 // The mock write results of transaction 1 and the first attempt of
6208 // transaction 2.
6209 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:066210 MockWrite(SYNCHRONOUS, 64), // GET
6211 MockWrite(SYNCHRONOUS, 93), // POST
6212 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:516213 };
[email protected]31a2bfe2010-02-09 08:03:396214 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6215 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:516216
6217 // The second socket is used for the second attempt of transaction 2.
6218
6219 // The response of transaction 2.
6220 MockRead data_reads2[] = {
6221 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
6222 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:066223 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:516224 };
6225 // The mock write results of the second attempt of transaction 2.
6226 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:066227 MockWrite(SYNCHRONOUS, 93), // POST
6228 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:516229 };
[email protected]31a2bfe2010-02-09 08:03:396230 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6231 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:516232
[email protected]bb88e1d32013-05-03 23:11:076233 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6234 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:516235
thestig9d3bb0c2015-01-24 00:49:516236 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:516237 "hello world", "welcome"
6238 };
6239
6240 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:426241 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506242 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]372d34a2008-11-05 21:30:516243
[email protected]49639fa2011-12-20 23:22:416244 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:516245
[email protected]49639fa2011-12-20 23:22:416246 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426247 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:516248
6249 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426250 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:516251
[email protected]1c773ea12009-04-28 19:58:426252 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506253 ASSERT_TRUE(response != NULL);
[email protected]372d34a2008-11-05 21:30:516254
[email protected]90499482013-06-01 00:39:506255 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]372d34a2008-11-05 21:30:516256 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6257
6258 std::string response_data;
6259 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:426260 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:516261 EXPECT_EQ(kExpectedResponseData[i], response_data);
6262 }
6263}
[email protected]f9ee6b52008-11-08 06:46:236264
6265// Test the request-challenge-retry sequence for basic auth when there is
6266// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:166267// it fails the identity from the URL is used to answer the challenge.
[email protected]23e482282013-06-14 16:08:026268TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:426269 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236270 request.method = "GET";
bncce36dca22015-04-21 22:11:236271 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:416272 request.load_flags = LOAD_NORMAL;
[email protected]a97cca42009-08-14 01:00:296273
mmenkee65e7af2015-10-13 17:16:426274 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276275 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416276 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276277
[email protected]a97cca42009-08-14 01:00:296278 // The password contains an escaped character -- for this test to pass it
6279 // will need to be unescaped by HttpNetworkTransaction.
6280 EXPECT_EQ("b%40r", request.url.password());
6281
[email protected]f9ee6b52008-11-08 06:46:236282 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236283 MockWrite(
6284 "GET / HTTP/1.1\r\n"
6285 "Host: www.example.org\r\n"
6286 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236287 };
6288
6289 MockRead data_reads1[] = {
6290 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6291 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6292 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066293 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236294 };
6295
[email protected]2262e3a2012-05-22 16:08:166296 // After the challenge above, the transaction will be restarted using the
6297 // identity from the url (foo, b@r) to answer the challenge.
6298 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236299 MockWrite(
6300 "GET / HTTP/1.1\r\n"
6301 "Host: www.example.org\r\n"
6302 "Connection: keep-alive\r\n"
6303 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166304 };
6305
6306 MockRead data_reads2[] = {
6307 MockRead("HTTP/1.0 200 OK\r\n"),
6308 MockRead("Content-Length: 100\r\n\r\n"),
6309 MockRead(SYNCHRONOUS, OK),
6310 };
6311
[email protected]31a2bfe2010-02-09 08:03:396312 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6313 data_writes1, arraysize(data_writes1));
[email protected]2262e3a2012-05-22 16:08:166314 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6315 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076316 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6317 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236318
[email protected]49639fa2011-12-20 23:22:416319 TestCompletionCallback callback1;
[email protected]49639fa2011-12-20 23:22:416320 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426321 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236322 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426323 EXPECT_EQ(OK, rv);
[email protected]2262e3a2012-05-22 16:08:166324 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6325
6326 TestCompletionCallback callback2;
6327 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6328 EXPECT_EQ(ERR_IO_PENDING, rv);
6329 rv = callback2.WaitForResult();
6330 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226331 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6332
[email protected]2262e3a2012-05-22 16:08:166333 const HttpResponseInfo* response = trans->GetResponseInfo();
6334 ASSERT_TRUE(response != NULL);
6335
6336 // There is no challenge info, since the identity in URL worked.
6337 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6338
6339 EXPECT_EQ(100, response->headers->GetContentLength());
6340
6341 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:346342 base::MessageLoop::current()->RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:166343}
6344
6345// Test the request-challenge-retry sequence for basic auth when there is an
6346// incorrect identity in the URL. The identity from the URL should be used only
6347// once.
[email protected]23e482282013-06-14 16:08:026348TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:166349 HttpRequestInfo request;
6350 request.method = "GET";
6351 // Note: the URL has a username:password in it. The password "baz" is
6352 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:236353 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:166354
6355 request.load_flags = LOAD_NORMAL;
6356
mmenkee65e7af2015-10-13 17:16:426357 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2262e3a2012-05-22 16:08:166358 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416359 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2262e3a2012-05-22 16:08:166360
6361 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236362 MockWrite(
6363 "GET / HTTP/1.1\r\n"
6364 "Host: www.example.org\r\n"
6365 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166366 };
6367
6368 MockRead data_reads1[] = {
6369 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6370 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6371 MockRead("Content-Length: 10\r\n\r\n"),
6372 MockRead(SYNCHRONOUS, ERR_FAILED),
6373 };
6374
6375 // After the challenge above, the transaction will be restarted using the
6376 // identity from the url (foo, baz) to answer the challenge.
6377 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236378 MockWrite(
6379 "GET / HTTP/1.1\r\n"
6380 "Host: www.example.org\r\n"
6381 "Connection: keep-alive\r\n"
6382 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166383 };
6384
6385 MockRead data_reads2[] = {
6386 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6387 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6388 MockRead("Content-Length: 10\r\n\r\n"),
6389 MockRead(SYNCHRONOUS, ERR_FAILED),
6390 };
6391
6392 // After the challenge above, the transaction will be restarted using the
6393 // identity supplied by the user (foo, bar) to answer the challenge.
6394 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236395 MockWrite(
6396 "GET / HTTP/1.1\r\n"
6397 "Host: www.example.org\r\n"
6398 "Connection: keep-alive\r\n"
6399 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166400 };
6401
6402 MockRead data_reads3[] = {
6403 MockRead("HTTP/1.0 200 OK\r\n"),
6404 MockRead("Content-Length: 100\r\n\r\n"),
6405 MockRead(SYNCHRONOUS, OK),
6406 };
6407
6408 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6409 data_writes1, arraysize(data_writes1));
6410 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6411 data_writes2, arraysize(data_writes2));
6412 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6413 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:076414 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6415 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6416 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:166417
6418 TestCompletionCallback callback1;
6419
6420 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6421 EXPECT_EQ(ERR_IO_PENDING, rv);
6422
6423 rv = callback1.WaitForResult();
6424 EXPECT_EQ(OK, rv);
6425
6426 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6427 TestCompletionCallback callback2;
6428 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
6429 EXPECT_EQ(ERR_IO_PENDING, rv);
6430 rv = callback2.WaitForResult();
6431 EXPECT_EQ(OK, rv);
6432 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6433
6434 const HttpResponseInfo* response = trans->GetResponseInfo();
6435 ASSERT_TRUE(response != NULL);
6436 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6437
6438 TestCompletionCallback callback3;
6439 rv = trans->RestartWithAuth(
6440 AuthCredentials(kFoo, kBar), callback3.callback());
6441 EXPECT_EQ(ERR_IO_PENDING, rv);
6442 rv = callback3.WaitForResult();
6443 EXPECT_EQ(OK, rv);
6444 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6445
6446 response = trans->GetResponseInfo();
6447 ASSERT_TRUE(response != NULL);
6448
6449 // There is no challenge info, since the identity worked.
6450 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6451
6452 EXPECT_EQ(100, response->headers->GetContentLength());
6453
[email protected]ea9dc9a2009-09-05 00:43:326454 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:346455 base::MessageLoop::current()->RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:326456}
6457
[email protected]2217aa22013-10-11 03:03:546458
6459// Test the request-challenge-retry sequence for basic auth when there is a
6460// correct identity in the URL, but its use is being suppressed. The identity
6461// from the URL should never be used.
6462TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
6463 HttpRequestInfo request;
6464 request.method = "GET";
bncce36dca22015-04-21 22:11:236465 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:546466 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
6467
mmenkee65e7af2015-10-13 17:16:426468 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2217aa22013-10-11 03:03:546469 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416470 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2217aa22013-10-11 03:03:546471
6472 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236473 MockWrite(
6474 "GET / HTTP/1.1\r\n"
6475 "Host: www.example.org\r\n"
6476 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:546477 };
6478
6479 MockRead data_reads1[] = {
6480 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6481 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6482 MockRead("Content-Length: 10\r\n\r\n"),
6483 MockRead(SYNCHRONOUS, ERR_FAILED),
6484 };
6485
6486 // After the challenge above, the transaction will be restarted using the
6487 // identity supplied by the user, not the one in the URL, to answer the
6488 // challenge.
6489 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236490 MockWrite(
6491 "GET / HTTP/1.1\r\n"
6492 "Host: www.example.org\r\n"
6493 "Connection: keep-alive\r\n"
6494 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:546495 };
6496
6497 MockRead data_reads3[] = {
6498 MockRead("HTTP/1.0 200 OK\r\n"),
6499 MockRead("Content-Length: 100\r\n\r\n"),
6500 MockRead(SYNCHRONOUS, OK),
6501 };
6502
6503 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6504 data_writes1, arraysize(data_writes1));
6505 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6506 data_writes3, arraysize(data_writes3));
6507 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6508 session_deps_.socket_factory->AddSocketDataProvider(&data3);
6509
6510 TestCompletionCallback callback1;
6511 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
6512 EXPECT_EQ(ERR_IO_PENDING, rv);
6513 rv = callback1.WaitForResult();
6514 EXPECT_EQ(OK, rv);
6515 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6516
6517 const HttpResponseInfo* response = trans->GetResponseInfo();
6518 ASSERT_TRUE(response != NULL);
6519 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6520
6521 TestCompletionCallback callback3;
6522 rv = trans->RestartWithAuth(
6523 AuthCredentials(kFoo, kBar), callback3.callback());
6524 EXPECT_EQ(ERR_IO_PENDING, rv);
6525 rv = callback3.WaitForResult();
6526 EXPECT_EQ(OK, rv);
6527 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6528
6529 response = trans->GetResponseInfo();
6530 ASSERT_TRUE(response != NULL);
6531
6532 // There is no challenge info, since the identity worked.
6533 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6534 EXPECT_EQ(100, response->headers->GetContentLength());
6535
6536 // Empty the current queue.
6537 base::MessageLoop::current()->RunUntilIdle();
6538}
6539
[email protected]f9ee6b52008-11-08 06:46:236540// Test that previously tried username/passwords for a realm get re-used.
[email protected]23e482282013-06-14 16:08:026541TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
mmenkee65e7af2015-10-13 17:16:426542 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:236543
6544 // Transaction 1: authenticate (foo, bar) on MyRealm1
6545 {
[email protected]1c773ea12009-04-28 19:58:426546 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236547 request.method = "GET";
bncce36dca22015-04-21 22:11:236548 request.url = GURL("http://www.example.org/x/y/z");
[email protected]f9ee6b52008-11-08 06:46:236549 request.load_flags = 0;
6550
[email protected]262eec82013-03-19 21:01:366551 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506552 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276553
[email protected]f9ee6b52008-11-08 06:46:236554 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236555 MockWrite(
6556 "GET /x/y/z HTTP/1.1\r\n"
6557 "Host: www.example.org\r\n"
6558 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236559 };
6560
6561 MockRead data_reads1[] = {
6562 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6563 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6564 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066565 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236566 };
6567
6568 // Resend with authorization (username=foo, password=bar)
6569 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236570 MockWrite(
6571 "GET /x/y/z HTTP/1.1\r\n"
6572 "Host: www.example.org\r\n"
6573 "Connection: keep-alive\r\n"
6574 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236575 };
6576
6577 // Sever accepts the authorization.
6578 MockRead data_reads2[] = {
6579 MockRead("HTTP/1.0 200 OK\r\n"),
6580 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066581 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236582 };
6583
[email protected]31a2bfe2010-02-09 08:03:396584 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6585 data_writes1, arraysize(data_writes1));
6586 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6587 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076588 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6589 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236590
[email protected]49639fa2011-12-20 23:22:416591 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236592
[email protected]49639fa2011-12-20 23:22:416593 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426594 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236595
6596 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426597 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236598
[email protected]1c773ea12009-04-28 19:58:426599 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506600 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046601 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:236602
[email protected]49639fa2011-12-20 23:22:416603 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:236604
[email protected]49639fa2011-12-20 23:22:416605 rv = trans->RestartWithAuth(
6606 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426607 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236608
6609 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426610 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236611
6612 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506613 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236614 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6615 EXPECT_EQ(100, response->headers->GetContentLength());
6616 }
6617
6618 // ------------------------------------------------------------------------
6619
6620 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
6621 {
[email protected]1c773ea12009-04-28 19:58:426622 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236623 request.method = "GET";
6624 // Note that Transaction 1 was at /x/y/z, so this is in the same
6625 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:236626 request.url = GURL("http://www.example.org/x/y/a/b");
[email protected]f9ee6b52008-11-08 06:46:236627 request.load_flags = 0;
6628
[email protected]262eec82013-03-19 21:01:366629 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506630 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276631
[email protected]f9ee6b52008-11-08 06:46:236632 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236633 MockWrite(
6634 "GET /x/y/a/b HTTP/1.1\r\n"
6635 "Host: www.example.org\r\n"
6636 "Connection: keep-alive\r\n"
6637 // Send preemptive authorization for MyRealm1
6638 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236639 };
6640
6641 // The server didn't like the preemptive authorization, and
6642 // challenges us for a different realm (MyRealm2).
6643 MockRead data_reads1[] = {
6644 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6645 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
6646 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066647 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236648 };
6649
6650 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
6651 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236652 MockWrite(
6653 "GET /x/y/a/b HTTP/1.1\r\n"
6654 "Host: www.example.org\r\n"
6655 "Connection: keep-alive\r\n"
6656 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236657 };
6658
6659 // Sever accepts the authorization.
6660 MockRead data_reads2[] = {
6661 MockRead("HTTP/1.0 200 OK\r\n"),
6662 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066663 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236664 };
6665
[email protected]31a2bfe2010-02-09 08:03:396666 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6667 data_writes1, arraysize(data_writes1));
6668 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6669 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076670 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6671 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236672
[email protected]49639fa2011-12-20 23:22:416673 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236674
[email protected]49639fa2011-12-20 23:22:416675 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426676 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236677
6678 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426679 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236680
[email protected]1c773ea12009-04-28 19:58:426681 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506682 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046683 ASSERT_TRUE(response->auth_challenge.get());
6684 EXPECT_FALSE(response->auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:236685 EXPECT_EQ("www.example.org:80",
[email protected]79cb5c12011-09-12 13:12:046686 response->auth_challenge->challenger.ToString());
6687 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:196688 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:236689
[email protected]49639fa2011-12-20 23:22:416690 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:236691
[email protected]49639fa2011-12-20 23:22:416692 rv = trans->RestartWithAuth(
6693 AuthCredentials(kFoo2, kBar2), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426694 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236695
6696 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426697 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236698
6699 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506700 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236701 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6702 EXPECT_EQ(100, response->headers->GetContentLength());
6703 }
6704
6705 // ------------------------------------------------------------------------
6706
6707 // Transaction 3: Resend a request in MyRealm's protection space --
6708 // succeed with preemptive authorization.
6709 {
[email protected]1c773ea12009-04-28 19:58:426710 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236711 request.method = "GET";
bncce36dca22015-04-21 22:11:236712 request.url = GURL("http://www.example.org/x/y/z2");
[email protected]f9ee6b52008-11-08 06:46:236713 request.load_flags = 0;
6714
[email protected]262eec82013-03-19 21:01:366715 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506716 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276717
[email protected]f9ee6b52008-11-08 06:46:236718 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236719 MockWrite(
6720 "GET /x/y/z2 HTTP/1.1\r\n"
6721 "Host: www.example.org\r\n"
6722 "Connection: keep-alive\r\n"
6723 // The authorization for MyRealm1 gets sent preemptively
6724 // (since the url is in the same protection space)
6725 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236726 };
6727
6728 // Sever accepts the preemptive authorization
6729 MockRead data_reads1[] = {
6730 MockRead("HTTP/1.0 200 OK\r\n"),
6731 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066732 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236733 };
6734
[email protected]31a2bfe2010-02-09 08:03:396735 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6736 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:076737 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:236738
[email protected]49639fa2011-12-20 23:22:416739 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236740
[email protected]49639fa2011-12-20 23:22:416741 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426742 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236743
6744 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426745 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236746
[email protected]1c773ea12009-04-28 19:58:426747 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506748 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236749
6750 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6751 EXPECT_EQ(100, response->headers->GetContentLength());
6752 }
6753
6754 // ------------------------------------------------------------------------
6755
6756 // Transaction 4: request another URL in MyRealm (however the
6757 // url is not known to belong to the protection space, so no pre-auth).
6758 {
[email protected]1c773ea12009-04-28 19:58:426759 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236760 request.method = "GET";
bncce36dca22015-04-21 22:11:236761 request.url = GURL("http://www.example.org/x/1");
[email protected]f9ee6b52008-11-08 06:46:236762 request.load_flags = 0;
6763
[email protected]262eec82013-03-19 21:01:366764 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506765 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276766
[email protected]f9ee6b52008-11-08 06:46:236767 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236768 MockWrite(
6769 "GET /x/1 HTTP/1.1\r\n"
6770 "Host: www.example.org\r\n"
6771 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236772 };
6773
6774 MockRead data_reads1[] = {
6775 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6776 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6777 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066778 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236779 };
6780
6781 // Resend with authorization from MyRealm's cache.
6782 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236783 MockWrite(
6784 "GET /x/1 HTTP/1.1\r\n"
6785 "Host: www.example.org\r\n"
6786 "Connection: keep-alive\r\n"
6787 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236788 };
6789
6790 // Sever accepts the authorization.
6791 MockRead data_reads2[] = {
6792 MockRead("HTTP/1.0 200 OK\r\n"),
6793 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066794 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236795 };
6796
[email protected]31a2bfe2010-02-09 08:03:396797 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6798 data_writes1, arraysize(data_writes1));
6799 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6800 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076801 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6802 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236803
[email protected]49639fa2011-12-20 23:22:416804 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236805
[email protected]49639fa2011-12-20 23:22:416806 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426807 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236808
6809 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426810 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236811
[email protected]0757e7702009-03-27 04:00:226812 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:416813 TestCompletionCallback callback2;
6814 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426815 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:226816 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426817 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226818 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6819
[email protected]1c773ea12009-04-28 19:58:426820 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506821 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236822 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6823 EXPECT_EQ(100, response->headers->GetContentLength());
6824 }
6825
6826 // ------------------------------------------------------------------------
6827
6828 // Transaction 5: request a URL in MyRealm, but the server rejects the
6829 // cached identity. Should invalidate and re-prompt.
6830 {
[email protected]1c773ea12009-04-28 19:58:426831 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236832 request.method = "GET";
bncce36dca22015-04-21 22:11:236833 request.url = GURL("http://www.example.org/p/q/t");
[email protected]f9ee6b52008-11-08 06:46:236834 request.load_flags = 0;
6835
[email protected]262eec82013-03-19 21:01:366836 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506837 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276838
[email protected]f9ee6b52008-11-08 06:46:236839 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236840 MockWrite(
6841 "GET /p/q/t HTTP/1.1\r\n"
6842 "Host: www.example.org\r\n"
6843 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236844 };
6845
6846 MockRead data_reads1[] = {
6847 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6848 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6849 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066850 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236851 };
6852
6853 // Resend with authorization from cache for MyRealm.
6854 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236855 MockWrite(
6856 "GET /p/q/t HTTP/1.1\r\n"
6857 "Host: www.example.org\r\n"
6858 "Connection: keep-alive\r\n"
6859 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236860 };
6861
6862 // Sever rejects the authorization.
6863 MockRead data_reads2[] = {
6864 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6865 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6866 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066867 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236868 };
6869
6870 // At this point we should prompt for new credentials for MyRealm.
6871 // Restart with username=foo3, password=foo4.
6872 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236873 MockWrite(
6874 "GET /p/q/t HTTP/1.1\r\n"
6875 "Host: www.example.org\r\n"
6876 "Connection: keep-alive\r\n"
6877 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236878 };
6879
6880 // Sever accepts the authorization.
6881 MockRead data_reads3[] = {
6882 MockRead("HTTP/1.0 200 OK\r\n"),
6883 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066884 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236885 };
6886
[email protected]31a2bfe2010-02-09 08:03:396887 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6888 data_writes1, arraysize(data_writes1));
6889 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6890 data_writes2, arraysize(data_writes2));
6891 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6892 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:076893 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6894 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6895 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:236896
[email protected]49639fa2011-12-20 23:22:416897 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236898
[email protected]49639fa2011-12-20 23:22:416899 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:426900 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236901
6902 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426903 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236904
[email protected]0757e7702009-03-27 04:00:226905 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:416906 TestCompletionCallback callback2;
6907 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:426908 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:226909 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426910 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:226911 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6912
[email protected]1c773ea12009-04-28 19:58:426913 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506914 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046915 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:236916
[email protected]49639fa2011-12-20 23:22:416917 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:236918
[email protected]49639fa2011-12-20 23:22:416919 rv = trans->RestartWithAuth(
6920 AuthCredentials(kFoo3, kBar3), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:426921 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:236922
[email protected]0757e7702009-03-27 04:00:226923 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:426924 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:236925
6926 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506927 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:236928 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6929 EXPECT_EQ(100, response->headers->GetContentLength());
6930 }
6931}
[email protected]89ceba9a2009-03-21 03:46:066932
[email protected]3c32c5f2010-05-18 15:18:126933// Tests that nonce count increments when multiple auth attempts
6934// are started with the same nonce.
[email protected]23e482282013-06-14 16:08:026935TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:446936 HttpAuthHandlerDigest::Factory* digest_factory =
6937 new HttpAuthHandlerDigest::Factory();
6938 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
6939 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6940 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:076941 session_deps_.http_auth_handler_factory.reset(digest_factory);
mmenkee65e7af2015-10-13 17:16:426942 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:126943
6944 // Transaction 1: authenticate (foo, bar) on MyRealm1
6945 {
[email protected]3c32c5f2010-05-18 15:18:126946 HttpRequestInfo request;
6947 request.method = "GET";
bncce36dca22015-04-21 22:11:236948 request.url = GURL("http://www.example.org/x/y/z");
[email protected]3c32c5f2010-05-18 15:18:126949 request.load_flags = 0;
6950
[email protected]262eec82013-03-19 21:01:366951 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506952 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276953
[email protected]3c32c5f2010-05-18 15:18:126954 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236955 MockWrite(
6956 "GET /x/y/z HTTP/1.1\r\n"
6957 "Host: www.example.org\r\n"
6958 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:126959 };
6960
6961 MockRead data_reads1[] = {
6962 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6963 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6964 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066965 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:126966 };
6967
6968 // Resend with authorization (username=foo, password=bar)
6969 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236970 MockWrite(
6971 "GET /x/y/z HTTP/1.1\r\n"
6972 "Host: www.example.org\r\n"
6973 "Connection: keep-alive\r\n"
6974 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6975 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6976 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6977 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:126978 };
6979
6980 // Sever accepts the authorization.
6981 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:086982 MockRead("HTTP/1.0 200 OK\r\n"),
6983 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:126984 };
6985
6986 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6987 data_writes1, arraysize(data_writes1));
6988 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6989 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076990 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6991 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:126992
[email protected]49639fa2011-12-20 23:22:416993 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:126994
[email protected]49639fa2011-12-20 23:22:416995 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:126996 EXPECT_EQ(ERR_IO_PENDING, rv);
6997
6998 rv = callback1.WaitForResult();
6999 EXPECT_EQ(OK, rv);
7000
7001 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507002 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:047003 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
[email protected]3c32c5f2010-05-18 15:18:127004
[email protected]49639fa2011-12-20 23:22:417005 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:127006
[email protected]49639fa2011-12-20 23:22:417007 rv = trans->RestartWithAuth(
7008 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]3c32c5f2010-05-18 15:18:127009 EXPECT_EQ(ERR_IO_PENDING, rv);
7010
7011 rv = callback2.WaitForResult();
7012 EXPECT_EQ(OK, rv);
7013
7014 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507015 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:127016 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7017 }
7018
7019 // ------------------------------------------------------------------------
7020
7021 // Transaction 2: Request another resource in digestive's protection space.
7022 // This will preemptively add an Authorization header which should have an
7023 // "nc" value of 2 (as compared to 1 in the first use.
7024 {
[email protected]3c32c5f2010-05-18 15:18:127025 HttpRequestInfo request;
7026 request.method = "GET";
7027 // Note that Transaction 1 was at /x/y/z, so this is in the same
7028 // protection space as digest.
bncce36dca22015-04-21 22:11:237029 request.url = GURL("http://www.example.org/x/y/a/b");
[email protected]3c32c5f2010-05-18 15:18:127030 request.load_flags = 0;
7031
[email protected]262eec82013-03-19 21:01:367032 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507033 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277034
[email protected]3c32c5f2010-05-18 15:18:127035 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237036 MockWrite(
7037 "GET /x/y/a/b HTTP/1.1\r\n"
7038 "Host: www.example.org\r\n"
7039 "Connection: keep-alive\r\n"
7040 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
7041 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
7042 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
7043 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:127044 };
7045
7046 // Sever accepts the authorization.
7047 MockRead data_reads1[] = {
7048 MockRead("HTTP/1.0 200 OK\r\n"),
7049 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067050 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:127051 };
7052
7053 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7054 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:077055 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:127056
[email protected]49639fa2011-12-20 23:22:417057 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:127058
[email protected]49639fa2011-12-20 23:22:417059 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:127060 EXPECT_EQ(ERR_IO_PENDING, rv);
7061
7062 rv = callback1.WaitForResult();
7063 EXPECT_EQ(OK, rv);
7064
7065 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507066 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:127067 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7068 }
7069}
7070
[email protected]89ceba9a2009-03-21 03:46:067071// Test the ResetStateForRestart() private method.
[email protected]23e482282013-06-14 16:08:027072TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:067073 // Create a transaction (the dependencies aren't important).
mmenkee65e7af2015-10-13 17:16:427074 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:407075 scoped_ptr<HttpNetworkTransaction> trans(
dcheng48459ac22014-08-26 00:46:417076 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]89ceba9a2009-03-21 03:46:067077
7078 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:067079 trans->read_buf_ = new IOBuffer(15);
7080 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:207081 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:067082
7083 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:147084 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:577085 response->auth_challenge = new AuthChallengeInfo();
[email protected]70d66502011-09-23 00:55:087086 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:577087 response->response_time = base::Time::Now();
7088 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:067089
7090 { // Setup state for response_.vary_data
7091 HttpRequestInfo request;
7092 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
7093 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:277094 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:437095 request.extra_headers.SetHeader("Foo", "1");
7096 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:507097 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:067098 }
7099
7100 // Cause the above state to be reset.
7101 trans->ResetStateForRestart();
7102
7103 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:077104 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:067105 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:207106 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:577107 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7108 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:047109 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:087110 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:577111 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:067112}
7113
[email protected]bacff652009-03-31 17:50:337114// Test HTTPS connections to a site with a bad certificate
[email protected]23e482282013-06-14 16:08:027115TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:337116 HttpRequestInfo request;
7117 request.method = "GET";
bncce36dca22015-04-21 22:11:237118 request.url = GURL("https://www.example.org/");
[email protected]bacff652009-03-31 17:50:337119 request.load_flags = 0;
7120
mmenkee65e7af2015-10-13 17:16:427121 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277122 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417123 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277124
[email protected]bacff652009-03-31 17:50:337125 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237126 MockWrite(
7127 "GET / HTTP/1.1\r\n"
7128 "Host: www.example.org\r\n"
7129 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337130 };
7131
7132 MockRead data_reads[] = {
7133 MockRead("HTTP/1.0 200 OK\r\n"),
7134 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7135 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067136 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:337137 };
7138
[email protected]5ecc992a42009-11-11 01:41:597139 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:397140 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7141 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067142 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7143 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:337144
[email protected]bb88e1d32013-05-03 23:11:077145 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7146 session_deps_.socket_factory->AddSocketDataProvider(&data);
7147 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7148 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:337149
[email protected]49639fa2011-12-20 23:22:417150 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:337151
[email protected]49639fa2011-12-20 23:22:417152 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:337153 EXPECT_EQ(ERR_IO_PENDING, rv);
7154
7155 rv = callback.WaitForResult();
7156 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7157
[email protected]49639fa2011-12-20 23:22:417158 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:337159 EXPECT_EQ(ERR_IO_PENDING, rv);
7160
7161 rv = callback.WaitForResult();
7162 EXPECT_EQ(OK, rv);
7163
7164 const HttpResponseInfo* response = trans->GetResponseInfo();
7165
[email protected]fe2255a2011-09-20 19:37:507166 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:337167 EXPECT_EQ(100, response->headers->GetContentLength());
7168}
7169
7170// Test HTTPS connections to a site with a bad certificate, going through a
7171// proxy
[email protected]23e482282013-06-14 16:08:027172TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
rdsmith82957ad2015-09-16 19:42:037173 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]bacff652009-03-31 17:50:337174
7175 HttpRequestInfo request;
7176 request.method = "GET";
bncce36dca22015-04-21 22:11:237177 request.url = GURL("https://www.example.org/");
[email protected]bacff652009-03-31 17:50:337178 request.load_flags = 0;
7179
7180 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:177181 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7182 "Host: www.example.org:443\r\n"
7183 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337184 };
7185
7186 MockRead proxy_reads[] = {
7187 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067188 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:337189 };
7190
7191 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177192 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7193 "Host: www.example.org:443\r\n"
7194 "Proxy-Connection: keep-alive\r\n\r\n"),
7195 MockWrite("GET / HTTP/1.1\r\n"
7196 "Host: www.example.org\r\n"
7197 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337198 };
7199
7200 MockRead data_reads[] = {
7201 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7202 MockRead("HTTP/1.0 200 OK\r\n"),
7203 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7204 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067205 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:337206 };
7207
[email protected]31a2bfe2010-02-09 08:03:397208 StaticSocketDataProvider ssl_bad_certificate(
7209 proxy_reads, arraysize(proxy_reads),
7210 proxy_writes, arraysize(proxy_writes));
7211 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7212 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067213 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7214 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:337215
[email protected]bb88e1d32013-05-03 23:11:077216 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7217 session_deps_.socket_factory->AddSocketDataProvider(&data);
7218 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7219 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:337220
[email protected]49639fa2011-12-20 23:22:417221 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:337222
7223 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:077224 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:337225
mmenkee65e7af2015-10-13 17:16:427226 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:407227 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417228 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bacff652009-03-31 17:50:337229
[email protected]49639fa2011-12-20 23:22:417230 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:337231 EXPECT_EQ(ERR_IO_PENDING, rv);
7232
7233 rv = callback.WaitForResult();
7234 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7235
[email protected]49639fa2011-12-20 23:22:417236 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:337237 EXPECT_EQ(ERR_IO_PENDING, rv);
7238
7239 rv = callback.WaitForResult();
7240 EXPECT_EQ(OK, rv);
7241
7242 const HttpResponseInfo* response = trans->GetResponseInfo();
7243
[email protected]fe2255a2011-09-20 19:37:507244 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:337245 EXPECT_EQ(100, response->headers->GetContentLength());
7246 }
7247}
7248
[email protected]2df19bb2010-08-25 20:13:467249
7250// Test HTTPS connections to a site, going through an HTTPS proxy
[email protected]23e482282013-06-14 16:08:027251TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037252 session_deps_.proxy_service =
7253 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:517254 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:077255 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:467256
7257 HttpRequestInfo request;
7258 request.method = "GET";
bncce36dca22015-04-21 22:11:237259 request.url = GURL("https://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467260 request.load_flags = 0;
7261
7262 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177263 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7264 "Host: www.example.org:443\r\n"
7265 "Proxy-Connection: keep-alive\r\n\r\n"),
7266 MockWrite("GET / HTTP/1.1\r\n"
7267 "Host: www.example.org\r\n"
7268 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467269 };
7270
7271 MockRead data_reads[] = {
7272 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7273 MockRead("HTTP/1.1 200 OK\r\n"),
7274 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7275 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067276 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467277 };
7278
7279 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7280 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067281 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
7282 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:467283
[email protected]bb88e1d32013-05-03 23:11:077284 session_deps_.socket_factory->AddSocketDataProvider(&data);
7285 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
7286 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:467287
[email protected]49639fa2011-12-20 23:22:417288 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:467289
mmenkee65e7af2015-10-13 17:16:427290 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:467291 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417292 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2df19bb2010-08-25 20:13:467293
[email protected]49639fa2011-12-20 23:22:417294 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:467295 EXPECT_EQ(ERR_IO_PENDING, rv);
7296
7297 rv = callback.WaitForResult();
7298 EXPECT_EQ(OK, rv);
7299 const HttpResponseInfo* response = trans->GetResponseInfo();
7300
[email protected]fe2255a2011-09-20 19:37:507301 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:467302
7303 EXPECT_TRUE(response->headers->IsKeepAlive());
7304 EXPECT_EQ(200, response->headers->response_code());
7305 EXPECT_EQ(100, response->headers->GetContentLength());
7306 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:207307
7308 LoadTimingInfo load_timing_info;
7309 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7310 TestLoadTimingNotReusedWithPac(load_timing_info,
7311 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:467312}
7313
[email protected]511f6f52010-12-17 03:58:297314// Test an HTTPS Proxy's ability to redirect a CONNECT request
[email protected]23e482282013-06-14 16:08:027315TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037316 session_deps_.proxy_service =
7317 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:517318 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:077319 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:297320
7321 HttpRequestInfo request;
7322 request.method = "GET";
bncce36dca22015-04-21 22:11:237323 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297324 request.load_flags = 0;
7325
7326 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177327 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7328 "Host: www.example.org:443\r\n"
7329 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:297330 };
7331
7332 MockRead data_reads[] = {
7333 MockRead("HTTP/1.1 302 Redirect\r\n"),
7334 MockRead("Location: http://login.example.com/\r\n"),
7335 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067336 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:297337 };
7338
7339 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7340 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067341 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:297342
[email protected]bb88e1d32013-05-03 23:11:077343 session_deps_.socket_factory->AddSocketDataProvider(&data);
7344 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297345
[email protected]49639fa2011-12-20 23:22:417346 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297347
mmenkee65e7af2015-10-13 17:16:427348 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297349 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417350 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297351
[email protected]49639fa2011-12-20 23:22:417352 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297353 EXPECT_EQ(ERR_IO_PENDING, rv);
7354
7355 rv = callback.WaitForResult();
7356 EXPECT_EQ(OK, rv);
7357 const HttpResponseInfo* response = trans->GetResponseInfo();
7358
[email protected]fe2255a2011-09-20 19:37:507359 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:297360
7361 EXPECT_EQ(302, response->headers->response_code());
7362 std::string url;
7363 EXPECT_TRUE(response->headers->IsRedirect(&url));
7364 EXPECT_EQ("http://login.example.com/", url);
[email protected]029c83b62013-01-24 05:28:207365
7366 // In the case of redirects from proxies, HttpNetworkTransaction returns
7367 // timing for the proxy connection instead of the connection to the host,
7368 // and no send / receive times.
7369 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
7370 LoadTimingInfo load_timing_info;
7371 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7372
7373 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:297374 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:207375
7376 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
7377 EXPECT_LE(load_timing_info.proxy_resolve_start,
7378 load_timing_info.proxy_resolve_end);
7379 EXPECT_LE(load_timing_info.proxy_resolve_end,
7380 load_timing_info.connect_timing.connect_start);
7381 ExpectConnectTimingHasTimes(
7382 load_timing_info.connect_timing,
7383 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
7384
7385 EXPECT_TRUE(load_timing_info.send_start.is_null());
7386 EXPECT_TRUE(load_timing_info.send_end.is_null());
7387 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]511f6f52010-12-17 03:58:297388}
7389
7390// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
[email protected]23e482282013-06-14 16:08:027391TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
rdsmith82957ad2015-09-16 19:42:037392 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297393
7394 HttpRequestInfo request;
7395 request.method = "GET";
bncce36dca22015-04-21 22:11:237396 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297397 request.load_flags = 0;
7398
lgarrona91df87f2014-12-05 00:51:347399 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237400 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207401 scoped_ptr<SpdyFrame> goaway(
7402 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]511f6f52010-12-17 03:58:297403 MockWrite data_writes[] = {
rch8e6c6c42015-05-01 14:05:137404 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
7405 CreateMockWrite(*goaway.get(), 2, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:297406 };
7407
7408 static const char* const kExtraHeaders[] = {
7409 "location",
7410 "http://login.example.com/",
7411 };
[email protected]ff98d7f02012-03-22 21:44:197412 scoped_ptr<SpdyFrame> resp(
[email protected]23e482282013-06-14 16:08:027413 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
[email protected]511f6f52010-12-17 03:58:297414 arraysize(kExtraHeaders)/2, 1));
7415 MockRead data_reads[] = {
rch8e6c6c42015-05-01 14:05:137416 CreateMockRead(*resp.get(), 1), MockRead(ASYNC, 0, 3), // EOF
[email protected]511f6f52010-12-17 03:58:297417 };
7418
rch8e6c6c42015-05-01 14:05:137419 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
7420 arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067421 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
rdsmithebb50aa2015-11-12 03:44:387422 proxy_ssl.SetNextProto(GetProtocol());
[email protected]511f6f52010-12-17 03:58:297423
[email protected]bb88e1d32013-05-03 23:11:077424 session_deps_.socket_factory->AddSocketDataProvider(&data);
7425 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297426
[email protected]49639fa2011-12-20 23:22:417427 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297428
mmenkee65e7af2015-10-13 17:16:427429 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297430 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417431 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297432
[email protected]49639fa2011-12-20 23:22:417433 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297434 EXPECT_EQ(ERR_IO_PENDING, rv);
7435
7436 rv = callback.WaitForResult();
7437 EXPECT_EQ(OK, rv);
7438 const HttpResponseInfo* response = trans->GetResponseInfo();
7439
[email protected]fe2255a2011-09-20 19:37:507440 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:297441
7442 EXPECT_EQ(302, response->headers->response_code());
7443 std::string url;
7444 EXPECT_TRUE(response->headers->IsRedirect(&url));
7445 EXPECT_EQ("http://login.example.com/", url);
7446}
7447
[email protected]4eddbc732012-08-09 05:40:177448// Test that an HTTPS proxy's response to a CONNECT request is filtered.
[email protected]23e482282013-06-14 16:08:027449TEST_P(HttpNetworkTransactionTest,
[email protected]4eddbc732012-08-09 05:40:177450 ErrorResponseToHttpsConnectViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037451 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297452
7453 HttpRequestInfo request;
7454 request.method = "GET";
bncce36dca22015-04-21 22:11:237455 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297456 request.load_flags = 0;
7457
7458 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177459 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7460 "Host: www.example.org:443\r\n"
7461 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:297462 };
7463
7464 MockRead data_reads[] = {
7465 MockRead("HTTP/1.1 404 Not Found\r\n"),
7466 MockRead("Content-Length: 23\r\n\r\n"),
7467 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:067468 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:297469 };
7470
7471 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7472 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067473 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:297474
[email protected]bb88e1d32013-05-03 23:11:077475 session_deps_.socket_factory->AddSocketDataProvider(&data);
7476 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297477
[email protected]49639fa2011-12-20 23:22:417478 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297479
mmenkee65e7af2015-10-13 17:16:427480 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297481 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417482 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297483
[email protected]49639fa2011-12-20 23:22:417484 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297485 EXPECT_EQ(ERR_IO_PENDING, rv);
7486
7487 rv = callback.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:177488 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]511f6f52010-12-17 03:58:297489
[email protected]4eddbc732012-08-09 05:40:177490 // TODO(ttuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:297491}
7492
[email protected]4eddbc732012-08-09 05:40:177493// Test that a SPDY proxy's response to a CONNECT request is filtered.
[email protected]23e482282013-06-14 16:08:027494TEST_P(HttpNetworkTransactionTest,
[email protected]4eddbc732012-08-09 05:40:177495 ErrorResponseToHttpsConnectViaSpdyProxy) {
rdsmith82957ad2015-09-16 19:42:037496 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297497
7498 HttpRequestInfo request;
7499 request.method = "GET";
bncce36dca22015-04-21 22:11:237500 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297501 request.load_flags = 0;
7502
lgarrona91df87f2014-12-05 00:51:347503 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237504 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207505 scoped_ptr<SpdyFrame> rst(
7506 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]511f6f52010-12-17 03:58:297507 MockWrite data_writes[] = {
rch8e6c6c42015-05-01 14:05:137508 CreateMockWrite(*conn.get(), 0), CreateMockWrite(*rst.get(), 3),
[email protected]511f6f52010-12-17 03:58:297509 };
7510
7511 static const char* const kExtraHeaders[] = {
7512 "location",
7513 "http://login.example.com/",
7514 };
[email protected]ff98d7f02012-03-22 21:44:197515 scoped_ptr<SpdyFrame> resp(
[email protected]23e482282013-06-14 16:08:027516 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
[email protected]511f6f52010-12-17 03:58:297517 arraysize(kExtraHeaders)/2, 1));
[email protected]ff98d7f02012-03-22 21:44:197518 scoped_ptr<SpdyFrame> body(
[email protected]23e482282013-06-14 16:08:027519 spdy_util_.ConstructSpdyBodyFrame(
7520 1, "The host does not exist", 23, true));
[email protected]511f6f52010-12-17 03:58:297521 MockRead data_reads[] = {
rch8e6c6c42015-05-01 14:05:137522 CreateMockRead(*resp.get(), 1),
7523 CreateMockRead(*body.get(), 2),
7524 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:297525 };
7526
rch8e6c6c42015-05-01 14:05:137527 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
7528 arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067529 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
rdsmithebb50aa2015-11-12 03:44:387530 proxy_ssl.SetNextProto(GetProtocol());
[email protected]511f6f52010-12-17 03:58:297531
[email protected]bb88e1d32013-05-03 23:11:077532 session_deps_.socket_factory->AddSocketDataProvider(&data);
7533 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297534
[email protected]49639fa2011-12-20 23:22:417535 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297536
mmenkee65e7af2015-10-13 17:16:427537 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]511f6f52010-12-17 03:58:297538 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417539 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297540
[email protected]49639fa2011-12-20 23:22:417541 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:297542 EXPECT_EQ(ERR_IO_PENDING, rv);
7543
7544 rv = callback.WaitForResult();
[email protected]4eddbc732012-08-09 05:40:177545 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]511f6f52010-12-17 03:58:297546
[email protected]4eddbc732012-08-09 05:40:177547 // TODO(ttuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:297548}
7549
[email protected]0c5fb722012-02-28 11:50:357550// Test the request-challenge-retry sequence for basic auth, through
7551// a SPDY proxy over a single SPDY session.
[email protected]23e482282013-06-14 16:08:027552TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:357553 HttpRequestInfo request;
7554 request.method = "GET";
bncce36dca22015-04-21 22:11:237555 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:357556 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:297557 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]0c5fb722012-02-28 11:50:357558
7559 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037560 session_deps_.proxy_service =
7561 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
vishal.b62985ca92015-04-17 08:45:517562 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077563 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:427564 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:357565
7566 // Since we have proxy, should try to establish tunnel.
lgarrona91df87f2014-12-05 00:51:347567 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237568 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
[email protected]c10b20852013-05-15 21:29:207569 scoped_ptr<SpdyFrame> rst(
7570 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
rdsmithebb50aa2015-11-12 03:44:387571 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:357572
7573 // After calling trans->RestartWithAuth(), this is the request we should
7574 // be issuing -- the final header line contains the credentials.
7575 const char* const kAuthCredentials[] = {
7576 "proxy-authorization", "Basic Zm9vOmJhcg==",
7577 };
[email protected]fba2dbde2013-05-24 16:09:017578 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
lgarrona91df87f2014-12-05 00:51:347579 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
bncce36dca22015-04-21 22:11:237580 HostPortPair("www.example.org", 443)));
7581 // fetch https://www.example.org/ via HTTP
7582 const char get[] =
7583 "GET / HTTP/1.1\r\n"
7584 "Host: www.example.org\r\n"
7585 "Connection: keep-alive\r\n\r\n";
[email protected]ff98d7f02012-03-22 21:44:197586 scoped_ptr<SpdyFrame> wrapped_get(
[email protected]23e482282013-06-14 16:08:027587 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
[email protected]0c5fb722012-02-28 11:50:357588
7589 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137590 CreateMockWrite(*req, 0, ASYNC),
7591 CreateMockWrite(*rst, 2, ASYNC),
7592 CreateMockWrite(*connect2, 3),
7593 CreateMockWrite(*wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:357594 };
7595
7596 // The proxy responds to the connect with a 407, using a persistent
7597 // connection.
thestig9d3bb0c2015-01-24 00:49:517598 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:357599 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:357600 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
7601 };
[email protected]745aa9c2014-06-27 02:21:297602 scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
7603 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:357604
[email protected]23e482282013-06-14 16:08:027605 scoped_ptr<SpdyFrame> conn_resp(
7606 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]0c5fb722012-02-28 11:50:357607 const char resp[] = "HTTP/1.1 200 OK\r\n"
7608 "Content-Length: 5\r\n\r\n";
7609
[email protected]ff98d7f02012-03-22 21:44:197610 scoped_ptr<SpdyFrame> wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:027611 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
[email protected]ff98d7f02012-03-22 21:44:197612 scoped_ptr<SpdyFrame> wrapped_body(
[email protected]23e482282013-06-14 16:08:027613 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
[email protected]0c5fb722012-02-28 11:50:357614 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137615 CreateMockRead(*conn_auth_resp, 1, ASYNC),
7616 CreateMockRead(*conn_resp, 4, ASYNC),
7617 CreateMockRead(*wrapped_get_resp, 6, ASYNC),
7618 CreateMockRead(*wrapped_body, 7, ASYNC),
7619 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:357620 };
7621
rch8e6c6c42015-05-01 14:05:137622 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7623 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077624 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:357625 // Negotiate SPDY to the proxy
7626 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387627 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077628 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:357629 // Vanilla SSL to the server
7630 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077631 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:357632
7633 TestCompletionCallback callback1;
7634
[email protected]262eec82013-03-19 21:01:367635 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507636 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0c5fb722012-02-28 11:50:357637
7638 int rv = trans->Start(&request, callback1.callback(), log.bound());
7639 EXPECT_EQ(ERR_IO_PENDING, rv);
7640
7641 rv = callback1.WaitForResult();
7642 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:467643 TestNetLogEntry::List entries;
[email protected]0c5fb722012-02-28 11:50:357644 log.GetEntries(&entries);
7645 size_t pos = ExpectLogContainsSomewhere(
7646 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7647 NetLog::PHASE_NONE);
7648 ExpectLogContainsSomewhere(
7649 entries, pos,
7650 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7651 NetLog::PHASE_NONE);
7652
7653 const HttpResponseInfo* response = trans->GetResponseInfo();
7654 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:507655 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]0c5fb722012-02-28 11:50:357656 EXPECT_EQ(407, response->headers->response_code());
7657 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7658 EXPECT_TRUE(response->auth_challenge.get() != NULL);
7659 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
7660
7661 TestCompletionCallback callback2;
7662
7663 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
7664 callback2.callback());
7665 EXPECT_EQ(ERR_IO_PENDING, rv);
7666
7667 rv = callback2.WaitForResult();
7668 EXPECT_EQ(OK, rv);
7669
7670 response = trans->GetResponseInfo();
7671 ASSERT_TRUE(response != NULL);
7672
7673 EXPECT_TRUE(response->headers->IsKeepAlive());
7674 EXPECT_EQ(200, response->headers->response_code());
7675 EXPECT_EQ(5, response->headers->GetContentLength());
7676 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7677
7678 // The password prompt info should not be set.
7679 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7680
[email protected]029c83b62013-01-24 05:28:207681 LoadTimingInfo load_timing_info;
7682 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7683 TestLoadTimingNotReusedWithPac(load_timing_info,
7684 CONNECT_TIMING_HAS_SSL_TIMES);
7685
[email protected]0c5fb722012-02-28 11:50:357686 trans.reset();
7687 session->CloseAllConnections();
7688}
7689
[email protected]7c6f7ba2012-04-03 04:09:297690// Test that an explicitly trusted SPDY proxy can push a resource from an
7691// origin that is different from that of its associated resource.
[email protected]23e482282013-06-14 16:08:027692TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
[email protected]7c6f7ba2012-04-03 04:09:297693 HttpRequestInfo request;
7694 HttpRequestInfo push_request;
7695
[email protected]7c6f7ba2012-04-03 04:09:297696 request.method = "GET";
bncce36dca22015-04-21 22:11:237697 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:297698 push_request.method = "GET";
7699 push_request.url = GURL("http://www.another-origin.com/foo.dat");
7700
[email protected]7c6f7ba2012-04-03 04:09:297701 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037702 session_deps_.proxy_service =
7703 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
vishal.b62985ca92015-04-17 08:45:517704 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077705 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:507706
7707 // Enable cross-origin push.
[email protected]bb88e1d32013-05-03 23:11:077708 session_deps_.trusted_spdy_proxy = "myproxy:70";
[email protected]61b4efc2012-04-27 18:12:507709
mmenkee65e7af2015-10-13 17:16:427710 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:297711
[email protected]cdf8f7e72013-05-23 10:56:467712 scoped_ptr<SpdyFrame> stream1_syn(
7713 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
[email protected]7c6f7ba2012-04-03 04:09:297714
7715 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137716 CreateMockWrite(*stream1_syn, 0, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:297717 };
7718
7719 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027720 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:297721
7722 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027723 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:297724
7725 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027726 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]7c6f7ba2012-04-03 04:09:297727 0,
7728 2,
7729 1,
7730 "http://www.another-origin.com/foo.dat"));
[email protected]8a0fc822013-06-27 20:52:437731 const char kPushedData[] = "pushed";
7732 scoped_ptr<SpdyFrame> stream2_body(
7733 spdy_util_.ConstructSpdyBodyFrame(
7734 2, kPushedData, strlen(kPushedData), true));
[email protected]7c6f7ba2012-04-03 04:09:297735
7736 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137737 CreateMockRead(*stream1_reply, 1, ASYNC),
7738 CreateMockRead(*stream2_syn, 2, ASYNC),
7739 CreateMockRead(*stream1_body, 3, ASYNC),
7740 CreateMockRead(*stream2_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:597741 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:297742 };
7743
rch8e6c6c42015-05-01 14:05:137744 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7745 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077746 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:297747 // Negotiate SPDY to the proxy
7748 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387749 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077750 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:297751
[email protected]262eec82013-03-19 21:01:367752 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507753 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7c6f7ba2012-04-03 04:09:297754 TestCompletionCallback callback;
7755 int rv = trans->Start(&request, callback.callback(), log.bound());
7756 EXPECT_EQ(ERR_IO_PENDING, rv);
7757
7758 rv = callback.WaitForResult();
7759 EXPECT_EQ(OK, rv);
7760 const HttpResponseInfo* response = trans->GetResponseInfo();
7761
[email protected]262eec82013-03-19 21:01:367762 scoped_ptr<HttpTransaction> push_trans(
[email protected]90499482013-06-01 00:39:507763 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7764 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
[email protected]7c6f7ba2012-04-03 04:09:297765 EXPECT_EQ(ERR_IO_PENDING, rv);
7766
7767 rv = callback.WaitForResult();
7768 EXPECT_EQ(OK, rv);
7769 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
7770
7771 ASSERT_TRUE(response != NULL);
7772 EXPECT_TRUE(response->headers->IsKeepAlive());
7773
7774 EXPECT_EQ(200, response->headers->response_code());
7775 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7776
7777 std::string response_data;
7778 rv = ReadTransaction(trans.get(), &response_data);
7779 EXPECT_EQ(OK, rv);
7780 EXPECT_EQ("hello!", response_data);
7781
[email protected]029c83b62013-01-24 05:28:207782 LoadTimingInfo load_timing_info;
7783 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7784 TestLoadTimingNotReusedWithPac(load_timing_info,
7785 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7786
[email protected]7c6f7ba2012-04-03 04:09:297787 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:507788 EXPECT_TRUE(push_response->headers.get() != NULL);
[email protected]7c6f7ba2012-04-03 04:09:297789 EXPECT_EQ(200, push_response->headers->response_code());
7790
7791 rv = ReadTransaction(push_trans.get(), &response_data);
7792 EXPECT_EQ(OK, rv);
7793 EXPECT_EQ("pushed", response_data);
7794
[email protected]029c83b62013-01-24 05:28:207795 LoadTimingInfo push_load_timing_info;
7796 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
7797 TestLoadTimingReusedWithPac(push_load_timing_info);
7798 // The transactions should share a socket ID, despite being for different
7799 // origins.
7800 EXPECT_EQ(load_timing_info.socket_log_id,
7801 push_load_timing_info.socket_log_id);
7802
[email protected]7c6f7ba2012-04-03 04:09:297803 trans.reset();
7804 push_trans.reset();
7805 session->CloseAllConnections();
7806}
7807
[email protected]8c843192012-04-05 07:15:007808// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
[email protected]23e482282013-06-14 16:08:027809TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
[email protected]8c843192012-04-05 07:15:007810 HttpRequestInfo request;
7811
7812 request.method = "GET";
bncce36dca22015-04-21 22:11:237813 request.url = GURL("http://www.example.org/");
[email protected]8c843192012-04-05 07:15:007814
[email protected]8c843192012-04-05 07:15:007815 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037816 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:517817 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077818 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:507819
7820 // Enable cross-origin push.
[email protected]bb88e1d32013-05-03 23:11:077821 session_deps_.trusted_spdy_proxy = "myproxy:70";
[email protected]61b4efc2012-04-27 18:12:507822
mmenkee65e7af2015-10-13 17:16:427823 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:007824
[email protected]cdf8f7e72013-05-23 10:56:467825 scoped_ptr<SpdyFrame> stream1_syn(
7826 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
[email protected]8c843192012-04-05 07:15:007827
7828 scoped_ptr<SpdyFrame> push_rst(
[email protected]c10b20852013-05-15 21:29:207829 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:007830
7831 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137832 CreateMockWrite(*stream1_syn, 0, ASYNC), CreateMockWrite(*push_rst, 3),
[email protected]8c843192012-04-05 07:15:007833 };
7834
7835 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027836 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8c843192012-04-05 07:15:007837
7838 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027839 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]8c843192012-04-05 07:15:007840
7841 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027842 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]8c843192012-04-05 07:15:007843 0,
7844 2,
7845 1,
7846 "https://www.another-origin.com/foo.dat"));
7847
7848 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137849 CreateMockRead(*stream1_reply, 1, ASYNC),
7850 CreateMockRead(*stream2_syn, 2, ASYNC),
7851 CreateMockRead(*stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:597852 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:007853 };
7854
rch8e6c6c42015-05-01 14:05:137855 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7856 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077857 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:007858 // Negotiate SPDY to the proxy
7859 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387860 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077861 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:007862
[email protected]262eec82013-03-19 21:01:367863 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507864 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c843192012-04-05 07:15:007865 TestCompletionCallback callback;
7866 int rv = trans->Start(&request, callback.callback(), log.bound());
7867 EXPECT_EQ(ERR_IO_PENDING, rv);
7868
7869 rv = callback.WaitForResult();
7870 EXPECT_EQ(OK, rv);
7871 const HttpResponseInfo* response = trans->GetResponseInfo();
7872
7873 ASSERT_TRUE(response != NULL);
7874 EXPECT_TRUE(response->headers->IsKeepAlive());
7875
7876 EXPECT_EQ(200, response->headers->response_code());
7877 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7878
7879 std::string response_data;
7880 rv = ReadTransaction(trans.get(), &response_data);
7881 EXPECT_EQ(OK, rv);
7882 EXPECT_EQ("hello!", response_data);
7883
7884 trans.reset();
7885 session->CloseAllConnections();
7886}
7887
[email protected]2df19bb2010-08-25 20:13:467888// Test HTTPS connections to a site with a bad certificate, going through an
7889// HTTPS proxy
[email protected]23e482282013-06-14 16:08:027890TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037891 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]2df19bb2010-08-25 20:13:467892
7893 HttpRequestInfo request;
7894 request.method = "GET";
bncce36dca22015-04-21 22:11:237895 request.url = GURL("https://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467896 request.load_flags = 0;
7897
7898 // Attempt to fetch the URL from a server with a bad cert
7899 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:177900 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7901 "Host: www.example.org:443\r\n"
7902 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467903 };
7904
7905 MockRead bad_cert_reads[] = {
7906 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067907 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:467908 };
7909
7910 // Attempt to fetch the URL with a good cert
7911 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177912 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7913 "Host: www.example.org:443\r\n"
7914 "Proxy-Connection: keep-alive\r\n\r\n"),
7915 MockWrite("GET / HTTP/1.1\r\n"
7916 "Host: www.example.org\r\n"
7917 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467918 };
7919
7920 MockRead good_cert_reads[] = {
7921 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7922 MockRead("HTTP/1.0 200 OK\r\n"),
7923 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7924 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067925 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467926 };
7927
7928 StaticSocketDataProvider ssl_bad_certificate(
7929 bad_cert_reads, arraysize(bad_cert_reads),
7930 bad_cert_writes, arraysize(bad_cert_writes));
7931 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
7932 good_data_writes, arraysize(good_data_writes));
[email protected]8ddf8322012-02-23 18:08:067933 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7934 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:467935
7936 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:077937 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7938 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7939 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:467940
7941 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:077942 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7943 session_deps_.socket_factory->AddSocketDataProvider(&data);
7944 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:467945
[email protected]49639fa2011-12-20 23:22:417946 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:467947
mmenkee65e7af2015-10-13 17:16:427948 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:467949 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417950 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2df19bb2010-08-25 20:13:467951
[email protected]49639fa2011-12-20 23:22:417952 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:467953 EXPECT_EQ(ERR_IO_PENDING, rv);
7954
7955 rv = callback.WaitForResult();
7956 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
7957
[email protected]49639fa2011-12-20 23:22:417958 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]2df19bb2010-08-25 20:13:467959 EXPECT_EQ(ERR_IO_PENDING, rv);
7960
7961 rv = callback.WaitForResult();
7962 EXPECT_EQ(OK, rv);
7963
7964 const HttpResponseInfo* response = trans->GetResponseInfo();
7965
[email protected]fe2255a2011-09-20 19:37:507966 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:467967 EXPECT_EQ(100, response->headers->GetContentLength());
7968}
7969
[email protected]23e482282013-06-14 16:08:027970TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:427971 HttpRequestInfo request;
7972 request.method = "GET";
bncce36dca22015-04-21 22:11:237973 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:437974 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
7975 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:427976
mmenkee65e7af2015-10-13 17:16:427977 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277978 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417979 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277980
[email protected]1c773ea12009-04-28 19:58:427981 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237982 MockWrite(
7983 "GET / HTTP/1.1\r\n"
7984 "Host: www.example.org\r\n"
7985 "Connection: keep-alive\r\n"
7986 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:427987 };
7988
7989 // Lastly, the server responds with the actual content.
7990 MockRead data_reads[] = {
7991 MockRead("HTTP/1.0 200 OK\r\n"),
7992 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7993 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067994 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:427995 };
7996
[email protected]31a2bfe2010-02-09 08:03:397997 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7998 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:077999 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428000
[email protected]49639fa2011-12-20 23:22:418001 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428002
[email protected]49639fa2011-12-20 23:22:418003 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428004 EXPECT_EQ(ERR_IO_PENDING, rv);
8005
8006 rv = callback.WaitForResult();
8007 EXPECT_EQ(OK, rv);
8008}
8009
[email protected]23e482282013-06-14 16:08:028010TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:298011 HttpRequestInfo request;
8012 request.method = "GET";
bncce36dca22015-04-21 22:11:238013 request.url = GURL("https://www.example.org/");
[email protected]da81f132010-08-18 23:39:298014 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
8015 "Chromium Ultra Awesome X Edition");
8016
rdsmith82957ad2015-09-16 19:42:038017 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:428018 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278019 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418020 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278021
[email protected]da81f132010-08-18 23:39:298022 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:178023 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8024 "Host: www.example.org:443\r\n"
8025 "Proxy-Connection: keep-alive\r\n"
8026 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]da81f132010-08-18 23:39:298027 };
8028 MockRead data_reads[] = {
8029 // Return an error, so the transaction stops here (this test isn't
8030 // interested in the rest).
8031 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
8032 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8033 MockRead("Proxy-Connection: close\r\n\r\n"),
8034 };
8035
8036 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8037 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078038 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:298039
[email protected]49639fa2011-12-20 23:22:418040 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:298041
[email protected]49639fa2011-12-20 23:22:418042 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]da81f132010-08-18 23:39:298043 EXPECT_EQ(ERR_IO_PENDING, rv);
8044
8045 rv = callback.WaitForResult();
8046 EXPECT_EQ(OK, rv);
8047}
8048
[email protected]23e482282013-06-14 16:08:028049TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:428050 HttpRequestInfo request;
8051 request.method = "GET";
bncce36dca22015-04-21 22:11:238052 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428053 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:168054 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
8055 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:428056
mmenkee65e7af2015-10-13 17:16:428057 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278058 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418059 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278060
[email protected]1c773ea12009-04-28 19:58:428061 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238062 MockWrite(
8063 "GET / HTTP/1.1\r\n"
8064 "Host: www.example.org\r\n"
8065 "Connection: keep-alive\r\n"
8066 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428067 };
8068
8069 // Lastly, the server responds with the actual content.
8070 MockRead data_reads[] = {
8071 MockRead("HTTP/1.0 200 OK\r\n"),
8072 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8073 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068074 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428075 };
8076
[email protected]31a2bfe2010-02-09 08:03:398077 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8078 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078079 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428080
[email protected]49639fa2011-12-20 23:22:418081 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428082
[email protected]49639fa2011-12-20 23:22:418083 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428084 EXPECT_EQ(ERR_IO_PENDING, rv);
8085
8086 rv = callback.WaitForResult();
8087 EXPECT_EQ(OK, rv);
8088}
8089
[email protected]23e482282013-06-14 16:08:028090TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428091 HttpRequestInfo request;
8092 request.method = "POST";
bncce36dca22015-04-21 22:11:238093 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428094
mmenkee65e7af2015-10-13 17:16:428095 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278096 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418097 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278098
[email protected]1c773ea12009-04-28 19:58:428099 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238100 MockWrite(
8101 "POST / HTTP/1.1\r\n"
8102 "Host: www.example.org\r\n"
8103 "Connection: keep-alive\r\n"
8104 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428105 };
8106
8107 // Lastly, the server responds with the actual content.
8108 MockRead data_reads[] = {
8109 MockRead("HTTP/1.0 200 OK\r\n"),
8110 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8111 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068112 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428113 };
8114
[email protected]31a2bfe2010-02-09 08:03:398115 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8116 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078117 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428118
[email protected]49639fa2011-12-20 23:22:418119 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428120
[email protected]49639fa2011-12-20 23:22:418121 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428122 EXPECT_EQ(ERR_IO_PENDING, rv);
8123
8124 rv = callback.WaitForResult();
8125 EXPECT_EQ(OK, rv);
8126}
8127
[email protected]23e482282013-06-14 16:08:028128TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428129 HttpRequestInfo request;
8130 request.method = "PUT";
bncce36dca22015-04-21 22:11:238131 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428132
mmenkee65e7af2015-10-13 17:16:428133 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278134 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418135 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278136
[email protected]1c773ea12009-04-28 19:58:428137 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238138 MockWrite(
8139 "PUT / HTTP/1.1\r\n"
8140 "Host: www.example.org\r\n"
8141 "Connection: keep-alive\r\n"
8142 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428143 };
8144
8145 // Lastly, the server responds with the actual content.
8146 MockRead data_reads[] = {
8147 MockRead("HTTP/1.0 200 OK\r\n"),
8148 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8149 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068150 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428151 };
8152
[email protected]31a2bfe2010-02-09 08:03:398153 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8154 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078155 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428156
[email protected]49639fa2011-12-20 23:22:418157 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428158
[email protected]49639fa2011-12-20 23:22:418159 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428160 EXPECT_EQ(ERR_IO_PENDING, rv);
8161
8162 rv = callback.WaitForResult();
8163 EXPECT_EQ(OK, rv);
8164}
8165
[email protected]23e482282013-06-14 16:08:028166TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428167 HttpRequestInfo request;
8168 request.method = "HEAD";
bncce36dca22015-04-21 22:11:238169 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428170
mmenkee65e7af2015-10-13 17:16:428171 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278172 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418173 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278174
[email protected]1c773ea12009-04-28 19:58:428175 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:138176 MockWrite("HEAD / HTTP/1.1\r\n"
8177 "Host: www.example.org\r\n"
8178 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428179 };
8180
8181 // Lastly, the server responds with the actual content.
8182 MockRead data_reads[] = {
8183 MockRead("HTTP/1.0 200 OK\r\n"),
8184 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8185 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068186 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428187 };
8188
[email protected]31a2bfe2010-02-09 08:03:398189 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8190 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078191 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428192
[email protected]49639fa2011-12-20 23:22:418193 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428194
[email protected]49639fa2011-12-20 23:22:418195 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428196 EXPECT_EQ(ERR_IO_PENDING, rv);
8197
8198 rv = callback.WaitForResult();
8199 EXPECT_EQ(OK, rv);
8200}
8201
[email protected]23e482282013-06-14 16:08:028202TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:428203 HttpRequestInfo request;
8204 request.method = "GET";
bncce36dca22015-04-21 22:11:238205 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428206 request.load_flags = LOAD_BYPASS_CACHE;
8207
mmenkee65e7af2015-10-13 17:16:428208 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278209 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418210 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278211
[email protected]1c773ea12009-04-28 19:58:428212 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238213 MockWrite(
8214 "GET / HTTP/1.1\r\n"
8215 "Host: www.example.org\r\n"
8216 "Connection: keep-alive\r\n"
8217 "Pragma: no-cache\r\n"
8218 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428219 };
8220
8221 // Lastly, the server responds with the actual content.
8222 MockRead data_reads[] = {
8223 MockRead("HTTP/1.0 200 OK\r\n"),
8224 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8225 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068226 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428227 };
8228
[email protected]31a2bfe2010-02-09 08:03:398229 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8230 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078231 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428232
[email protected]49639fa2011-12-20 23:22:418233 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428234
[email protected]49639fa2011-12-20 23:22:418235 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428236 EXPECT_EQ(ERR_IO_PENDING, rv);
8237
8238 rv = callback.WaitForResult();
8239 EXPECT_EQ(OK, rv);
8240}
8241
[email protected]23e482282013-06-14 16:08:028242TEST_P(HttpNetworkTransactionTest,
[email protected]1c773ea12009-04-28 19:58:428243 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:428244 HttpRequestInfo request;
8245 request.method = "GET";
bncce36dca22015-04-21 22:11:238246 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428247 request.load_flags = LOAD_VALIDATE_CACHE;
8248
mmenkee65e7af2015-10-13 17:16:428249 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278250 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418251 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278252
[email protected]1c773ea12009-04-28 19:58:428253 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238254 MockWrite(
8255 "GET / HTTP/1.1\r\n"
8256 "Host: www.example.org\r\n"
8257 "Connection: keep-alive\r\n"
8258 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428259 };
8260
8261 // Lastly, the server responds with the actual content.
8262 MockRead data_reads[] = {
8263 MockRead("HTTP/1.0 200 OK\r\n"),
8264 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8265 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068266 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428267 };
8268
[email protected]31a2bfe2010-02-09 08:03:398269 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8270 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078271 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428272
[email protected]49639fa2011-12-20 23:22:418273 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428274
[email protected]49639fa2011-12-20 23:22:418275 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428276 EXPECT_EQ(ERR_IO_PENDING, rv);
8277
8278 rv = callback.WaitForResult();
8279 EXPECT_EQ(OK, rv);
8280}
8281
[email protected]23e482282013-06-14 16:08:028282TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:428283 HttpRequestInfo request;
8284 request.method = "GET";
bncce36dca22015-04-21 22:11:238285 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438286 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:428287
mmenkee65e7af2015-10-13 17:16:428288 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278289 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418290 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278291
[email protected]1c773ea12009-04-28 19:58:428292 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238293 MockWrite(
8294 "GET / HTTP/1.1\r\n"
8295 "Host: www.example.org\r\n"
8296 "Connection: keep-alive\r\n"
8297 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428298 };
8299
8300 // Lastly, the server responds with the actual content.
8301 MockRead data_reads[] = {
8302 MockRead("HTTP/1.0 200 OK\r\n"),
8303 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8304 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068305 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428306 };
8307
[email protected]31a2bfe2010-02-09 08:03:398308 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8309 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078310 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428311
[email protected]49639fa2011-12-20 23:22:418312 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428313
[email protected]49639fa2011-12-20 23:22:418314 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428315 EXPECT_EQ(ERR_IO_PENDING, rv);
8316
8317 rv = callback.WaitForResult();
8318 EXPECT_EQ(OK, rv);
8319}
8320
[email protected]23e482282013-06-14 16:08:028321TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:478322 HttpRequestInfo request;
8323 request.method = "GET";
bncce36dca22015-04-21 22:11:238324 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438325 request.extra_headers.SetHeader("referer", "www.foo.com");
8326 request.extra_headers.SetHeader("hEllo", "Kitty");
8327 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:478328
mmenkee65e7af2015-10-13 17:16:428329 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278330 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418331 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278332
[email protected]270c6412010-03-29 22:02:478333 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238334 MockWrite(
8335 "GET / HTTP/1.1\r\n"
8336 "Host: www.example.org\r\n"
8337 "Connection: keep-alive\r\n"
8338 "referer: www.foo.com\r\n"
8339 "hEllo: Kitty\r\n"
8340 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:478341 };
8342
8343 // Lastly, the server responds with the actual content.
8344 MockRead data_reads[] = {
8345 MockRead("HTTP/1.0 200 OK\r\n"),
8346 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8347 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068348 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:478349 };
8350
8351 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8352 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078353 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:478354
[email protected]49639fa2011-12-20 23:22:418355 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:478356
[email protected]49639fa2011-12-20 23:22:418357 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]270c6412010-03-29 22:02:478358 EXPECT_EQ(ERR_IO_PENDING, rv);
8359
8360 rv = callback.WaitForResult();
8361 EXPECT_EQ(OK, rv);
8362}
8363
[email protected]23e482282013-06-14 16:08:028364TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278365 HttpRequestInfo request;
8366 request.method = "GET";
bncce36dca22015-04-21 22:11:238367 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278368 request.load_flags = 0;
8369
rdsmith82957ad2015-09-16 19:42:038370 session_deps_.proxy_service =
8371 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518372 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078373 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028374
mmenkee65e7af2015-10-13 17:16:428375 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3cd17242009-06-23 02:59:028376 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418377 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028378
[email protected]3cd17242009-06-23 02:59:028379 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8380 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8381
8382 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238383 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8384 MockWrite(
8385 "GET / HTTP/1.1\r\n"
8386 "Host: www.example.org\r\n"
8387 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028388
8389 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:068390 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:028391 MockRead("HTTP/1.0 200 OK\r\n"),
8392 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8393 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068394 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028395 };
8396
[email protected]31a2bfe2010-02-09 08:03:398397 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8398 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078399 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028400
[email protected]49639fa2011-12-20 23:22:418401 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028402
[email protected]49639fa2011-12-20 23:22:418403 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:028404 EXPECT_EQ(ERR_IO_PENDING, rv);
8405
8406 rv = callback.WaitForResult();
8407 EXPECT_EQ(OK, rv);
8408
8409 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508410 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:028411
[email protected]029c83b62013-01-24 05:28:208412 LoadTimingInfo load_timing_info;
8413 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8414 TestLoadTimingNotReusedWithPac(load_timing_info,
8415 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8416
[email protected]3cd17242009-06-23 02:59:028417 std::string response_text;
8418 rv = ReadTransaction(trans.get(), &response_text);
8419 EXPECT_EQ(OK, rv);
8420 EXPECT_EQ("Payload", response_text);
8421}
8422
[email protected]23e482282013-06-14 16:08:028423TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278424 HttpRequestInfo request;
8425 request.method = "GET";
bncce36dca22015-04-21 22:11:238426 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278427 request.load_flags = 0;
8428
rdsmith82957ad2015-09-16 19:42:038429 session_deps_.proxy_service =
8430 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518431 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078432 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028433
mmenkee65e7af2015-10-13 17:16:428434 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3cd17242009-06-23 02:59:028435 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418436 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028437
[email protected]3cd17242009-06-23 02:59:028438 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
8439 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8440
8441 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238442 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
8443 arraysize(write_buffer)),
8444 MockWrite(
8445 "GET / HTTP/1.1\r\n"
8446 "Host: www.example.org\r\n"
8447 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028448
8449 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018450 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
8451 arraysize(read_buffer)),
[email protected]e0c27be2009-07-15 13:09:358452 MockRead("HTTP/1.0 200 OK\r\n"),
8453 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8454 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068455 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358456 };
8457
[email protected]31a2bfe2010-02-09 08:03:398458 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8459 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078460 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358461
[email protected]8ddf8322012-02-23 18:08:068462 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078463 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:358464
[email protected]49639fa2011-12-20 23:22:418465 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358466
[email protected]49639fa2011-12-20 23:22:418467 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:358468 EXPECT_EQ(ERR_IO_PENDING, rv);
8469
8470 rv = callback.WaitForResult();
8471 EXPECT_EQ(OK, rv);
8472
[email protected]029c83b62013-01-24 05:28:208473 LoadTimingInfo load_timing_info;
8474 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8475 TestLoadTimingNotReusedWithPac(load_timing_info,
8476 CONNECT_TIMING_HAS_SSL_TIMES);
8477
[email protected]e0c27be2009-07-15 13:09:358478 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508479 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:358480
8481 std::string response_text;
8482 rv = ReadTransaction(trans.get(), &response_text);
8483 EXPECT_EQ(OK, rv);
8484 EXPECT_EQ("Payload", response_text);
8485}
8486
[email protected]23e482282013-06-14 16:08:028487TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:208488 HttpRequestInfo request;
8489 request.method = "GET";
bncce36dca22015-04-21 22:11:238490 request.url = GURL("http://www.example.org/");
[email protected]029c83b62013-01-24 05:28:208491 request.load_flags = 0;
8492
rdsmith82957ad2015-09-16 19:42:038493 session_deps_.proxy_service =
8494 ProxyService::CreateFixed("socks4://myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518495 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078496 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:208497
mmenkee65e7af2015-10-13 17:16:428498 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:208499 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418500 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:208501
8502 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8503 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8504
8505 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238506 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8507 MockWrite(
8508 "GET / HTTP/1.1\r\n"
8509 "Host: www.example.org\r\n"
8510 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:208511
8512 MockRead data_reads[] = {
8513 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
8514 MockRead("HTTP/1.0 200 OK\r\n"),
8515 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8516 MockRead("Payload"),
8517 MockRead(SYNCHRONOUS, OK)
8518 };
8519
8520 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8521 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078522 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:208523
8524 TestCompletionCallback callback;
8525
8526 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8527 EXPECT_EQ(ERR_IO_PENDING, rv);
8528
8529 rv = callback.WaitForResult();
8530 EXPECT_EQ(OK, rv);
8531
8532 const HttpResponseInfo* response = trans->GetResponseInfo();
8533 ASSERT_TRUE(response != NULL);
8534
8535 LoadTimingInfo load_timing_info;
8536 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8537 TestLoadTimingNotReused(load_timing_info,
8538 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8539
8540 std::string response_text;
8541 rv = ReadTransaction(trans.get(), &response_text);
8542 EXPECT_EQ(OK, rv);
8543 EXPECT_EQ("Payload", response_text);
8544}
8545
[email protected]23e482282013-06-14 16:08:028546TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278547 HttpRequestInfo request;
8548 request.method = "GET";
bncce36dca22015-04-21 22:11:238549 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278550 request.load_flags = 0;
8551
rdsmith82957ad2015-09-16 19:42:038552 session_deps_.proxy_service =
8553 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518554 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078555 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358556
mmenkee65e7af2015-10-13 17:16:428557 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e0c27be2009-07-15 13:09:358558 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418559 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358560
[email protected]e0c27be2009-07-15 13:09:358561 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8562 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378563 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238564 0x05, // Version
8565 0x01, // Command (CONNECT)
8566 0x00, // Reserved.
8567 0x03, // Address type (DOMAINNAME).
8568 0x0F, // Length of domain (15)
8569 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8570 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:378571 };
[email protected]e0c27be2009-07-15 13:09:358572 const char kSOCKS5OkResponse[] =
8573 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
8574
8575 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238576 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8577 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
8578 MockWrite(
8579 "GET / HTTP/1.1\r\n"
8580 "Host: www.example.org\r\n"
8581 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358582
8583 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018584 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8585 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]e0c27be2009-07-15 13:09:358586 MockRead("HTTP/1.0 200 OK\r\n"),
8587 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8588 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068589 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358590 };
8591
[email protected]31a2bfe2010-02-09 08:03:398592 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8593 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078594 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358595
[email protected]49639fa2011-12-20 23:22:418596 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358597
[email protected]49639fa2011-12-20 23:22:418598 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:358599 EXPECT_EQ(ERR_IO_PENDING, rv);
8600
8601 rv = callback.WaitForResult();
8602 EXPECT_EQ(OK, rv);
8603
8604 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508605 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:358606
[email protected]029c83b62013-01-24 05:28:208607 LoadTimingInfo load_timing_info;
8608 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8609 TestLoadTimingNotReusedWithPac(load_timing_info,
8610 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8611
[email protected]e0c27be2009-07-15 13:09:358612 std::string response_text;
8613 rv = ReadTransaction(trans.get(), &response_text);
8614 EXPECT_EQ(OK, rv);
8615 EXPECT_EQ("Payload", response_text);
8616}
8617
[email protected]23e482282013-06-14 16:08:028618TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278619 HttpRequestInfo request;
8620 request.method = "GET";
bncce36dca22015-04-21 22:11:238621 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278622 request.load_flags = 0;
8623
rdsmith82957ad2015-09-16 19:42:038624 session_deps_.proxy_service =
8625 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518626 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078627 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358628
mmenkee65e7af2015-10-13 17:16:428629 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e0c27be2009-07-15 13:09:358630 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418631 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358632
[email protected]e0c27be2009-07-15 13:09:358633 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8634 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378635 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238636 0x05, // Version
8637 0x01, // Command (CONNECT)
8638 0x00, // Reserved.
8639 0x03, // Address type (DOMAINNAME).
8640 0x0F, // Length of domain (15)
8641 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8642 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:378643 };
8644
[email protected]e0c27be2009-07-15 13:09:358645 const char kSOCKS5OkResponse[] =
8646 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
8647
8648 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238649 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8650 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
8651 arraysize(kSOCKS5OkRequest)),
8652 MockWrite(
8653 "GET / HTTP/1.1\r\n"
8654 "Host: www.example.org\r\n"
8655 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358656
8657 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018658 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8659 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:028660 MockRead("HTTP/1.0 200 OK\r\n"),
8661 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8662 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068663 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028664 };
8665
[email protected]31a2bfe2010-02-09 08:03:398666 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8667 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078668 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028669
[email protected]8ddf8322012-02-23 18:08:068670 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078671 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:028672
[email protected]49639fa2011-12-20 23:22:418673 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028674
[email protected]49639fa2011-12-20 23:22:418675 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:028676 EXPECT_EQ(ERR_IO_PENDING, rv);
8677
8678 rv = callback.WaitForResult();
8679 EXPECT_EQ(OK, rv);
8680
8681 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508682 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:028683
[email protected]029c83b62013-01-24 05:28:208684 LoadTimingInfo load_timing_info;
8685 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8686 TestLoadTimingNotReusedWithPac(load_timing_info,
8687 CONNECT_TIMING_HAS_SSL_TIMES);
8688
[email protected]3cd17242009-06-23 02:59:028689 std::string response_text;
8690 rv = ReadTransaction(trans.get(), &response_text);
8691 EXPECT_EQ(OK, rv);
8692 EXPECT_EQ("Payload", response_text);
8693}
8694
[email protected]448d4ca52012-03-04 04:12:238695namespace {
8696
[email protected]04e5be32009-06-26 20:00:318697// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:068698
8699struct GroupNameTest {
8700 std::string proxy_server;
8701 std::string url;
8702 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:188703 bool ssl;
[email protected]2d731a32010-04-29 01:04:068704};
8705
mmenkee65e7af2015-10-13 17:16:428706scoped_ptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8a0fc822013-06-27 20:52:438707 NextProto next_proto,
[email protected]bb88e1d32013-05-03 23:11:078708 SpdySessionDependencies* session_deps_) {
mmenkee65e7af2015-10-13 17:16:428709 scoped_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:068710
[email protected]30d4c022013-07-18 22:58:168711 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:538712 session->http_server_properties();
bnccacc0992015-03-20 20:22:228713 AlternativeService alternative_service(
bnc4988e432015-03-31 03:06:258714 AlternateProtocolFromNextProto(next_proto), "", 443);
bnc7dc7e1b42015-07-28 14:43:128715 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:228716 http_server_properties->SetAlternativeService(
bnc7dc7e1b42015-07-28 14:43:128717 HostPortPair("host.with.alternate", 80), alternative_service, 1.0,
8718 expiration);
[email protected]2d731a32010-04-29 01:04:068719
8720 return session;
8721}
8722
mmenkee65e7af2015-10-13 17:16:428723int GroupNameTransactionHelper(const std::string& url,
8724 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:068725 HttpRequestInfo request;
8726 request.method = "GET";
8727 request.url = GURL(url);
8728 request.load_flags = 0;
8729
[email protected]262eec82013-03-19 21:01:368730 scoped_ptr<HttpTransaction> trans(
mmenkee65e7af2015-10-13 17:16:428731 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
[email protected]cb9bf6ca2011-01-28 13:15:278732
[email protected]49639fa2011-12-20 23:22:418733 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:068734
8735 // We do not complete this request, the dtor will clean the transaction up.
[email protected]49639fa2011-12-20 23:22:418736 return trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d731a32010-04-29 01:04:068737}
8738
[email protected]448d4ca52012-03-04 04:12:238739} // namespace
8740
[email protected]23e482282013-06-14 16:08:028741TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
[email protected]2d731a32010-04-29 01:04:068742 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238743 {
8744 "", // unused
8745 "http://www.example.org/direct",
8746 "www.example.org:80",
8747 false,
8748 },
8749 {
8750 "", // unused
8751 "http://[2001:1418:13:1::25]/direct",
8752 "[2001:1418:13:1::25]:80",
8753 false,
8754 },
[email protected]04e5be32009-06-26 20:00:318755
bncce36dca22015-04-21 22:11:238756 // SSL Tests
8757 {
8758 "", // unused
8759 "https://www.example.org/direct_ssl",
8760 "ssl/www.example.org:443",
8761 true,
8762 },
8763 {
8764 "", // unused
8765 "https://[2001:1418:13:1::25]/direct",
8766 "ssl/[2001:1418:13:1::25]:443",
8767 true,
8768 },
8769 {
8770 "", // unused
8771 "http://host.with.alternate/direct",
8772 "ssl/host.with.alternate:443",
8773 true,
8774 },
[email protected]2d731a32010-04-29 01:04:068775 };
[email protected]2ff8b312010-04-26 22:20:548776
bnc55ff9da2015-08-19 18:42:358777 session_deps_.use_alternative_services = true;
[email protected]2d731a32010-04-29 01:04:068778
viettrungluue4a8b882014-10-16 06:17:388779 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038780 session_deps_.proxy_service =
8781 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428782 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388783 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]2d731a32010-04-29 01:04:068784
mmenkee65e7af2015-10-13 17:16:428785 HttpNetworkSessionPeer peer(session.get());
[email protected]ab739042011-04-07 15:22:288786 CaptureGroupNameTransportSocketPool* transport_conn_pool =
8787 new CaptureGroupNameTransportSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138788 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348789 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]831e4a32013-11-14 02:14:448790 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8791 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028792 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
8793 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
dchengc7eeda422015-12-26 03:56:488794 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:068795
8796 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428797 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188798 if (tests[i].ssl)
8799 EXPECT_EQ(tests[i].expected_group_name,
8800 ssl_conn_pool->last_group_name_received());
8801 else
8802 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:288803 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:068804 }
[email protected]2d731a32010-04-29 01:04:068805}
8806
[email protected]23e482282013-06-14 16:08:028807TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
[email protected]2d731a32010-04-29 01:04:068808 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238809 {
8810 "http_proxy",
8811 "http://www.example.org/http_proxy_normal",
8812 "www.example.org:80",
8813 false,
8814 },
[email protected]2d731a32010-04-29 01:04:068815
bncce36dca22015-04-21 22:11:238816 // SSL Tests
8817 {
8818 "http_proxy",
8819 "https://www.example.org/http_connect_ssl",
8820 "ssl/www.example.org:443",
8821 true,
8822 },
[email protected]af3490e2010-10-16 21:02:298823
bncce36dca22015-04-21 22:11:238824 {
8825 "http_proxy",
8826 "http://host.with.alternate/direct",
8827 "ssl/host.with.alternate:443",
8828 true,
8829 },
[email protected]45499252013-01-23 17:12:568830
bncce36dca22015-04-21 22:11:238831 {
8832 "http_proxy",
8833 "ftp://ftp.google.com/http_proxy_normal",
8834 "ftp/ftp.google.com:21",
8835 false,
8836 },
[email protected]2d731a32010-04-29 01:04:068837 };
8838
bnc55ff9da2015-08-19 18:42:358839 session_deps_.use_alternative_services = true;
[email protected]2d731a32010-04-29 01:04:068840
viettrungluue4a8b882014-10-16 06:17:388841 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038842 session_deps_.proxy_service =
8843 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428844 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388845 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]2d731a32010-04-29 01:04:068846
mmenkee65e7af2015-10-13 17:16:428847 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:068848
[email protected]e60e47a2010-07-14 03:37:188849 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:138850 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:348851 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138852 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348853 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:028854
[email protected]831e4a32013-11-14 02:14:448855 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8856 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028857 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
8858 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchengc7eeda422015-12-26 03:56:488859 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:068860
8861 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428862 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188863 if (tests[i].ssl)
8864 EXPECT_EQ(tests[i].expected_group_name,
8865 ssl_conn_pool->last_group_name_received());
8866 else
8867 EXPECT_EQ(tests[i].expected_group_name,
8868 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:068869 }
[email protected]2d731a32010-04-29 01:04:068870}
8871
[email protected]23e482282013-06-14 16:08:028872TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
[email protected]2d731a32010-04-29 01:04:068873 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238874 {
8875 "socks4://socks_proxy:1080",
8876 "http://www.example.org/socks4_direct",
8877 "socks4/www.example.org:80",
8878 false,
8879 },
8880 {
8881 "socks5://socks_proxy:1080",
8882 "http://www.example.org/socks5_direct",
8883 "socks5/www.example.org:80",
8884 false,
8885 },
[email protected]2d731a32010-04-29 01:04:068886
bncce36dca22015-04-21 22:11:238887 // SSL Tests
8888 {
8889 "socks4://socks_proxy:1080",
8890 "https://www.example.org/socks4_ssl",
8891 "socks4/ssl/www.example.org:443",
8892 true,
8893 },
8894 {
8895 "socks5://socks_proxy:1080",
8896 "https://www.example.org/socks5_ssl",
8897 "socks5/ssl/www.example.org:443",
8898 true,
8899 },
[email protected]af3490e2010-10-16 21:02:298900
bncce36dca22015-04-21 22:11:238901 {
8902 "socks4://socks_proxy:1080",
8903 "http://host.with.alternate/direct",
8904 "socks4/ssl/host.with.alternate:443",
8905 true,
8906 },
[email protected]04e5be32009-06-26 20:00:318907 };
8908
bnc55ff9da2015-08-19 18:42:358909 session_deps_.use_alternative_services = true;
[email protected]2ff8b312010-04-26 22:20:548910
viettrungluue4a8b882014-10-16 06:17:388911 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038912 session_deps_.proxy_service =
8913 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428914 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388915 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]8b114dd72011-03-25 05:33:028916
mmenkee65e7af2015-10-13 17:16:428917 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:318918
[email protected]e60e47a2010-07-14 03:37:188919 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:138920 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348921 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138922 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348923 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:028924
[email protected]831e4a32013-11-14 02:14:448925 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8926 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028927 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
8928 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchengc7eeda422015-12-26 03:56:488929 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:318930
[email protected]262eec82013-03-19 21:01:368931 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:508932 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]04e5be32009-06-26 20:00:318933
[email protected]2d731a32010-04-29 01:04:068934 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428935 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188936 if (tests[i].ssl)
8937 EXPECT_EQ(tests[i].expected_group_name,
8938 ssl_conn_pool->last_group_name_received());
8939 else
8940 EXPECT_EQ(tests[i].expected_group_name,
8941 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:318942 }
8943}
8944
[email protected]23e482282013-06-14 16:08:028945TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:278946 HttpRequestInfo request;
8947 request.method = "GET";
bncce36dca22015-04-21 22:11:238948 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278949
rdsmith82957ad2015-09-16 19:42:038950 session_deps_.proxy_service =
8951 ProxyService::CreateFixed("myproxy:70;foobar:80");
[email protected]b59ff372009-07-15 22:04:328952
[email protected]69719062010-01-05 20:09:218953 // This simulates failure resolving all hostnames; that means we will fail
8954 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:078955 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:328956
mmenkee65e7af2015-10-13 17:16:428957 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]9172a982009-06-06 00:30:258958 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418959 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]9172a982009-06-06 00:30:258960
[email protected]49639fa2011-12-20 23:22:418961 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:258962
[email protected]49639fa2011-12-20 23:22:418963 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9172a982009-06-06 00:30:258964 EXPECT_EQ(ERR_IO_PENDING, rv);
8965
[email protected]9172a982009-06-06 00:30:258966 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:018967 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:258968}
8969
[email protected]685af592010-05-11 19:31:248970// Base test to make sure that when the load flags for a request specify to
8971// bypass the cache, the DNS cache is not used.
[email protected]23e482282013-06-14 16:08:028972void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
[email protected]bb88e1d32013-05-03 23:11:078973 int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:278974 // Issue a request, asking to bypass the cache(s).
8975 HttpRequestInfo request;
8976 request.method = "GET";
8977 request.load_flags = load_flags;
bncce36dca22015-04-21 22:11:238978 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278979
[email protected]a2c2fb92009-07-18 07:31:048980 // Select a host resolver that does caching.
[email protected]bb88e1d32013-05-03 23:11:078981 session_deps_.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:328982
mmenkee65e7af2015-10-13 17:16:428983 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:078984 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418985 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3b9cca42009-06-16 01:08:288986
bncce36dca22015-04-21 22:11:238987 // Warm up the host cache so it has an entry for "www.example.org".
[email protected]3b9cca42009-06-16 01:08:288988 AddressList addrlist;
[email protected]aa22b242011-11-16 18:58:298989 TestCompletionCallback callback;
[email protected]bb88e1d32013-05-03 23:11:078990 int rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:238991 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8992 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:478993 EXPECT_EQ(ERR_IO_PENDING, rv);
8994 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:288995 EXPECT_EQ(OK, rv);
8996
8997 // Verify that it was added to host cache, by doing a subsequent async lookup
8998 // and confirming it completes synchronously.
[email protected]bb88e1d32013-05-03 23:11:078999 rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:239000 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
9001 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:329002 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:289003
bncce36dca22015-04-21 22:11:239004 // Inject a failure the next time that "www.example.org" is resolved. This way
[email protected]3b9cca42009-06-16 01:08:289005 // we can tell if the next lookup hit the cache, or the "network".
9006 // (cache --> success, "network" --> failure).
bncce36dca22015-04-21 22:11:239007 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
[email protected]3b9cca42009-06-16 01:08:289008
9009 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
9010 // first read -- this won't be reached as the host resolution will fail first.
[email protected]8ddf8322012-02-23 18:08:069011 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:399012 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079013 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:289014
[email protected]3b9cca42009-06-16 01:08:289015 // Run the request.
[email protected]49639fa2011-12-20 23:22:419016 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:289017 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419018 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:289019
9020 // If we bypassed the cache, we would have gotten a failure while resolving
bncce36dca22015-04-21 22:11:239021 // "www.example.org".
[email protected]3b9cca42009-06-16 01:08:289022 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
9023}
9024
[email protected]685af592010-05-11 19:31:249025// There are multiple load flags that should trigger the host cache bypass.
9026// Test each in isolation:
[email protected]23e482282013-06-14 16:08:029027TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
[email protected]685af592010-05-11 19:31:249028 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
9029}
9030
[email protected]23e482282013-06-14 16:08:029031TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
[email protected]685af592010-05-11 19:31:249032 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
9033}
9034
[email protected]23e482282013-06-14 16:08:029035TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
[email protected]685af592010-05-11 19:31:249036 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
9037}
9038
[email protected]0877e3d2009-10-17 22:29:579039// Make sure we can handle an error when writing the request.
[email protected]23e482282013-06-14 16:08:029040TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:579041 HttpRequestInfo request;
9042 request.method = "GET";
9043 request.url = GURL("http://www.foo.com/");
9044 request.load_flags = 0;
9045
9046 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:069047 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:579048 };
[email protected]31a2bfe2010-02-09 08:03:399049 StaticSocketDataProvider data(NULL, 0,
9050 write_failure, arraysize(write_failure));
[email protected]bb88e1d32013-05-03 23:11:079051 session_deps_.socket_factory->AddSocketDataProvider(&data);
mmenkee65e7af2015-10-13 17:16:429052 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579053
[email protected]49639fa2011-12-20 23:22:419054 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579055
9056 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419057 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579058
[email protected]49639fa2011-12-20 23:22:419059 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579060 EXPECT_EQ(ERR_IO_PENDING, rv);
9061
9062 rv = callback.WaitForResult();
9063 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
ttuttled9dbc652015-09-29 20:00:599064
9065 IPEndPoint endpoint;
9066 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
9067 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:579068}
9069
zmo9528c9f42015-08-04 22:12:089070// Check that a connection closed after the start of the headers finishes ok.
9071TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:579072 HttpRequestInfo request;
9073 request.method = "GET";
9074 request.url = GURL("http://www.foo.com/");
9075 request.load_flags = 0;
9076
9077 MockRead data_reads[] = {
9078 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:069079 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:579080 };
9081
[email protected]31a2bfe2010-02-09 08:03:399082 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079083 session_deps_.socket_factory->AddSocketDataProvider(&data);
mmenkee65e7af2015-10-13 17:16:429084 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579085
[email protected]49639fa2011-12-20 23:22:419086 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579087
9088 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419089 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579090
[email protected]49639fa2011-12-20 23:22:419091 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579092 EXPECT_EQ(ERR_IO_PENDING, rv);
9093
9094 rv = callback.WaitForResult();
zmo9528c9f42015-08-04 22:12:089095 EXPECT_EQ(OK, rv);
9096
9097 const HttpResponseInfo* response = trans->GetResponseInfo();
9098 ASSERT_TRUE(response != NULL);
9099
9100 EXPECT_TRUE(response->headers.get() != NULL);
9101 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9102
9103 std::string response_data;
9104 rv = ReadTransaction(trans.get(), &response_data);
9105 EXPECT_EQ(OK, rv);
9106 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:599107
9108 IPEndPoint endpoint;
9109 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
9110 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:579111}
9112
9113// Make sure that a dropped connection while draining the body for auth
9114// restart does the right thing.
[email protected]23e482282013-06-14 16:08:029115TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:579116 HttpRequestInfo request;
9117 request.method = "GET";
bncce36dca22015-04-21 22:11:239118 request.url = GURL("http://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:579119 request.load_flags = 0;
9120
9121 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239122 MockWrite(
9123 "GET / HTTP/1.1\r\n"
9124 "Host: www.example.org\r\n"
9125 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:579126 };
9127
9128 MockRead data_reads1[] = {
9129 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
9130 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9131 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9132 MockRead("Content-Length: 14\r\n\r\n"),
9133 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:069134 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:579135 };
9136
[email protected]31a2bfe2010-02-09 08:03:399137 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9138 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:079139 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:579140
9141 // After calling trans->RestartWithAuth(), this is the request we should
9142 // be issuing -- the final header line contains the credentials.
9143 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239144 MockWrite(
9145 "GET / HTTP/1.1\r\n"
9146 "Host: www.example.org\r\n"
9147 "Connection: keep-alive\r\n"
9148 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:579149 };
9150
9151 // Lastly, the server responds with the actual content.
9152 MockRead data_reads2[] = {
9153 MockRead("HTTP/1.1 200 OK\r\n"),
9154 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9155 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069156 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:579157 };
9158
[email protected]31a2bfe2010-02-09 08:03:399159 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9160 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:079161 session_deps_.socket_factory->AddSocketDataProvider(&data2);
mmenkee65e7af2015-10-13 17:16:429162 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579163
[email protected]49639fa2011-12-20 23:22:419164 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:579165
[email protected]262eec82013-03-19 21:01:369166 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509167 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509168
[email protected]49639fa2011-12-20 23:22:419169 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579170 EXPECT_EQ(ERR_IO_PENDING, rv);
9171
9172 rv = callback1.WaitForResult();
9173 EXPECT_EQ(OK, rv);
9174
9175 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509176 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049177 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:579178
[email protected]49639fa2011-12-20 23:22:419179 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:579180
[email protected]49639fa2011-12-20 23:22:419181 rv = trans->RestartWithAuth(
9182 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]0877e3d2009-10-17 22:29:579183 EXPECT_EQ(ERR_IO_PENDING, rv);
9184
9185 rv = callback2.WaitForResult();
9186 EXPECT_EQ(OK, rv);
9187
9188 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509189 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:579190 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9191 EXPECT_EQ(100, response->headers->GetContentLength());
9192}
9193
9194// Test HTTPS connections going through a proxy that sends extra data.
[email protected]23e482282013-06-14 16:08:029195TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
rdsmith82957ad2015-09-16 19:42:039196 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]0877e3d2009-10-17 22:29:579197
9198 HttpRequestInfo request;
9199 request.method = "GET";
bncce36dca22015-04-21 22:11:239200 request.url = GURL("https://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:579201 request.load_flags = 0;
9202
9203 MockRead proxy_reads[] = {
9204 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:069205 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:579206 };
9207
[email protected]31a2bfe2010-02-09 08:03:399208 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]8ddf8322012-02-23 18:08:069209 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:579210
[email protected]bb88e1d32013-05-03 23:11:079211 session_deps_.socket_factory->AddSocketDataProvider(&data);
9212 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:579213
[email protected]49639fa2011-12-20 23:22:419214 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579215
[email protected]bb88e1d32013-05-03 23:11:079216 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:579217
mmenkee65e7af2015-10-13 17:16:429218 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579219 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419220 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579221
[email protected]49639fa2011-12-20 23:22:419222 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579223 EXPECT_EQ(ERR_IO_PENDING, rv);
9224
9225 rv = callback.WaitForResult();
9226 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
9227}
9228
[email protected]23e482282013-06-14 16:08:029229TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:469230 HttpRequestInfo request;
9231 request.method = "GET";
bncce36dca22015-04-21 22:11:239232 request.url = GURL("http://www.example.org/");
[email protected]9492e4a2010-02-24 00:58:469233 request.load_flags = 0;
9234
mmenkee65e7af2015-10-13 17:16:429235 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279236 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419237 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:279238
[email protected]e22e1362009-11-23 21:31:129239 MockRead data_reads[] = {
9240 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069241 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:129242 };
[email protected]9492e4a2010-02-24 00:58:469243
9244 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079245 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:469246
[email protected]49639fa2011-12-20 23:22:419247 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:469248
[email protected]49639fa2011-12-20 23:22:419249 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:469250 EXPECT_EQ(ERR_IO_PENDING, rv);
9251
9252 EXPECT_EQ(OK, callback.WaitForResult());
9253
9254 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509255 ASSERT_TRUE(response != NULL);
[email protected]9492e4a2010-02-24 00:58:469256
[email protected]90499482013-06-01 00:39:509257 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]9492e4a2010-02-24 00:58:469258 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9259
9260 std::string response_data;
9261 rv = ReadTransaction(trans.get(), &response_data);
[email protected]5543cbb2012-04-20 16:35:239262 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
[email protected]e22e1362009-11-23 21:31:129263}
9264
[email protected]23e482282013-06-14 16:08:029265TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:159266 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:529267 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:149268 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:219269 UploadFileElementReader::ScopedOverridingContentLengthForTests
9270 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:339271
olli.raula6df48b2a2015-11-26 07:40:229272 std::vector<scoped_ptr<UploadElementReader>> element_readers;
9273 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
avibf0746c2015-12-09 19:53:149274 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
9275 std::numeric_limits<uint64_t>::max(), base::Time())));
olli.raula6df48b2a2015-11-26 07:40:229276 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279277
9278 HttpRequestInfo request;
9279 request.method = "POST";
bncce36dca22015-04-21 22:11:239280 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279281 request.upload_data_stream = &upload_data_stream;
9282 request.load_flags = 0;
9283
mmenkee65e7af2015-10-13 17:16:429284 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]329b68b2012-11-14 17:54:279285 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419286 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]95d88ffe2010-02-04 21:25:339287
9288 MockRead data_reads[] = {
9289 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9290 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069291 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:339292 };
[email protected]31a2bfe2010-02-09 08:03:399293 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079294 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:339295
[email protected]49639fa2011-12-20 23:22:419296 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:339297
[email protected]49639fa2011-12-20 23:22:419298 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:339299 EXPECT_EQ(ERR_IO_PENDING, rv);
9300
9301 rv = callback.WaitForResult();
9302 EXPECT_EQ(OK, rv);
9303
9304 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509305 ASSERT_TRUE(response != NULL);
[email protected]95d88ffe2010-02-04 21:25:339306
[email protected]90499482013-06-01 00:39:509307 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]95d88ffe2010-02-04 21:25:339308 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9309
9310 std::string response_data;
9311 rv = ReadTransaction(trans.get(), &response_data);
9312 EXPECT_EQ(OK, rv);
9313 EXPECT_EQ("hello world", response_data);
9314
[email protected]dd3aa792013-07-16 19:10:239315 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:339316}
9317
[email protected]23e482282013-06-14 16:08:029318TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:159319 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:529320 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:369321 std::string temp_file_content("Unreadable file.");
[email protected]e5c2a22e2014-03-06 20:42:309322 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
[email protected]6624b4622010-03-29 19:58:369323 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:119324 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:369325
olli.raula6df48b2a2015-11-26 07:40:229326 std::vector<scoped_ptr<UploadElementReader>> element_readers;
avibf0746c2015-12-09 19:53:149327 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
9328 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
9329 std::numeric_limits<uint64_t>::max(), base::Time())));
olli.raula6df48b2a2015-11-26 07:40:229330 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279331
9332 HttpRequestInfo request;
9333 request.method = "POST";
bncce36dca22015-04-21 22:11:239334 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279335 request.upload_data_stream = &upload_data_stream;
9336 request.load_flags = 0;
9337
[email protected]999dd8c2013-11-12 06:45:549338 // If we try to upload an unreadable file, the transaction should fail.
mmenkee65e7af2015-10-13 17:16:429339 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]329b68b2012-11-14 17:54:279340 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419341 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]6624b4622010-03-29 19:58:369342
[email protected]999dd8c2013-11-12 06:45:549343 StaticSocketDataProvider data(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079344 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:369345
[email protected]49639fa2011-12-20 23:22:419346 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:369347
[email protected]49639fa2011-12-20 23:22:419348 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:369349 EXPECT_EQ(ERR_IO_PENDING, rv);
9350
9351 rv = callback.WaitForResult();
[email protected]999dd8c2013-11-12 06:45:549352 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
[email protected]6624b4622010-03-29 19:58:369353
[email protected]dd3aa792013-07-16 19:10:239354 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:369355}
9356
[email protected]02cad5d2013-10-02 08:14:039357TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
9358 class FakeUploadElementReader : public UploadElementReader {
9359 public:
9360 FakeUploadElementReader() {}
dchengb03027d2014-10-21 12:00:209361 ~FakeUploadElementReader() override {}
[email protected]02cad5d2013-10-02 08:14:039362
9363 const CompletionCallback& callback() const { return callback_; }
9364
9365 // UploadElementReader overrides:
dchengb03027d2014-10-21 12:00:209366 int Init(const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039367 callback_ = callback;
9368 return ERR_IO_PENDING;
9369 }
avibf0746c2015-12-09 19:53:149370 uint64_t GetContentLength() const override { return 0; }
9371 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:209372 int Read(IOBuffer* buf,
9373 int buf_length,
9374 const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039375 return ERR_FAILED;
9376 }
9377
9378 private:
9379 CompletionCallback callback_;
9380 };
9381
9382 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
olli.raula6df48b2a2015-11-26 07:40:229383 std::vector<scoped_ptr<UploadElementReader>> element_readers;
9384 element_readers.push_back(make_scoped_ptr(fake_reader));
9385 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:039386
9387 HttpRequestInfo request;
9388 request.method = "POST";
bncce36dca22015-04-21 22:11:239389 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:039390 request.upload_data_stream = &upload_data_stream;
9391 request.load_flags = 0;
9392
mmenkee65e7af2015-10-13 17:16:429393 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02cad5d2013-10-02 08:14:039394 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419395 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02cad5d2013-10-02 08:14:039396
9397 StaticSocketDataProvider data;
9398 session_deps_.socket_factory->AddSocketDataProvider(&data);
9399
9400 TestCompletionCallback callback;
9401 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9402 EXPECT_EQ(ERR_IO_PENDING, rv);
9403 base::MessageLoop::current()->RunUntilIdle();
9404
9405 // Transaction is pending on request body initialization.
9406 ASSERT_FALSE(fake_reader->callback().is_null());
9407
9408 // Return Init()'s result after the transaction gets destroyed.
9409 trans.reset();
9410 fake_reader->callback().Run(OK); // Should not crash.
9411}
9412
[email protected]aeefc9e82010-02-19 16:18:279413// Tests that changes to Auth realms are treated like auth rejections.
[email protected]23e482282013-06-14 16:08:029414TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:279415 HttpRequestInfo request;
9416 request.method = "GET";
bncce36dca22015-04-21 22:11:239417 request.url = GURL("http://www.example.org/");
[email protected]aeefc9e82010-02-19 16:18:279418 request.load_flags = 0;
9419
9420 // First transaction will request a resource and receive a Basic challenge
9421 // with realm="first_realm".
9422 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239423 MockWrite(
9424 "GET / HTTP/1.1\r\n"
9425 "Host: www.example.org\r\n"
9426 "Connection: keep-alive\r\n"
9427 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279428 };
9429 MockRead data_reads1[] = {
9430 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9431 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9432 "\r\n"),
9433 };
9434
9435 // After calling trans->RestartWithAuth(), provide an Authentication header
9436 // for first_realm. The server will reject and provide a challenge with
9437 // second_realm.
9438 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239439 MockWrite(
9440 "GET / HTTP/1.1\r\n"
9441 "Host: www.example.org\r\n"
9442 "Connection: keep-alive\r\n"
9443 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
9444 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279445 };
9446 MockRead data_reads2[] = {
9447 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9448 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
9449 "\r\n"),
9450 };
9451
9452 // This again fails, and goes back to first_realm. Make sure that the
9453 // entry is removed from cache.
9454 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239455 MockWrite(
9456 "GET / HTTP/1.1\r\n"
9457 "Host: www.example.org\r\n"
9458 "Connection: keep-alive\r\n"
9459 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
9460 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279461 };
9462 MockRead data_reads3[] = {
9463 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9464 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9465 "\r\n"),
9466 };
9467
9468 // Try one last time (with the correct password) and get the resource.
9469 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:239470 MockWrite(
9471 "GET / HTTP/1.1\r\n"
9472 "Host: www.example.org\r\n"
9473 "Connection: keep-alive\r\n"
9474 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
9475 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279476 };
9477 MockRead data_reads4[] = {
9478 MockRead("HTTP/1.1 200 OK\r\n"
9479 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:509480 "Content-Length: 5\r\n"
9481 "\r\n"
9482 "hello"),
[email protected]aeefc9e82010-02-19 16:18:279483 };
9484
9485 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9486 data_writes1, arraysize(data_writes1));
9487 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9488 data_writes2, arraysize(data_writes2));
9489 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
9490 data_writes3, arraysize(data_writes3));
9491 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
9492 data_writes4, arraysize(data_writes4));
[email protected]bb88e1d32013-05-03 23:11:079493 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9494 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9495 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9496 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:279497
[email protected]49639fa2011-12-20 23:22:419498 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:279499
mmenkee65e7af2015-10-13 17:16:429500 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0b0bf032010-09-21 18:08:509501 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419502 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509503
[email protected]aeefc9e82010-02-19 16:18:279504 // Issue the first request with Authorize headers. There should be a
9505 // password prompt for first_realm waiting to be filled in after the
9506 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419507 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:279508 EXPECT_EQ(ERR_IO_PENDING, rv);
9509 rv = callback1.WaitForResult();
9510 EXPECT_EQ(OK, rv);
9511 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509512 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049513 const AuthChallengeInfo* challenge = response->auth_challenge.get();
9514 ASSERT_FALSE(challenge == NULL);
9515 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239516 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049517 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199518 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279519
9520 // Issue the second request with an incorrect password. There should be a
9521 // password prompt for second_realm waiting to be filled in after the
9522 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419523 TestCompletionCallback callback2;
9524 rv = trans->RestartWithAuth(
9525 AuthCredentials(kFirst, kBaz), callback2.callback());
[email protected]aeefc9e82010-02-19 16:18:279526 EXPECT_EQ(ERR_IO_PENDING, rv);
9527 rv = callback2.WaitForResult();
9528 EXPECT_EQ(OK, rv);
9529 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509530 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049531 challenge = response->auth_challenge.get();
9532 ASSERT_FALSE(challenge == NULL);
9533 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239534 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049535 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199536 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279537
9538 // Issue the third request with another incorrect password. There should be
9539 // a password prompt for first_realm waiting to be filled in. If the password
9540 // prompt is not present, it indicates that the HttpAuthCacheEntry for
9541 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:419542 TestCompletionCallback callback3;
9543 rv = trans->RestartWithAuth(
9544 AuthCredentials(kSecond, kFou), callback3.callback());
[email protected]aeefc9e82010-02-19 16:18:279545 EXPECT_EQ(ERR_IO_PENDING, rv);
9546 rv = callback3.WaitForResult();
9547 EXPECT_EQ(OK, rv);
9548 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509549 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049550 challenge = response->auth_challenge.get();
9551 ASSERT_FALSE(challenge == NULL);
9552 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239553 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049554 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199555 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279556
9557 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:419558 TestCompletionCallback callback4;
9559 rv = trans->RestartWithAuth(
9560 AuthCredentials(kFirst, kBar), callback4.callback());
[email protected]aeefc9e82010-02-19 16:18:279561 EXPECT_EQ(ERR_IO_PENDING, rv);
9562 rv = callback4.WaitForResult();
9563 EXPECT_EQ(OK, rv);
9564 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509565 ASSERT_TRUE(response != NULL);
[email protected]aeefc9e82010-02-19 16:18:279566 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9567}
9568
bncc958faa2015-07-31 18:14:529569TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
9570 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359571 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529572
9573 std::string alternative_service_http_header =
9574 GetAlternativeServiceHttpHeader();
9575
9576 MockRead data_reads[] = {
9577 MockRead("HTTP/1.1 200 OK\r\n"),
9578 MockRead(alternative_service_http_header.c_str()),
9579 MockRead("\r\n"),
9580 MockRead("hello world"),
9581 MockRead(SYNCHRONOUS, OK),
9582 };
9583
9584 HttpRequestInfo request;
9585 request.method = "GET";
9586 request.url = GURL("http://www.example.org/");
9587 request.load_flags = 0;
9588
9589 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9590
9591 session_deps_.socket_factory->AddSocketDataProvider(&data);
9592
9593 TestCompletionCallback callback;
9594
mmenkee65e7af2015-10-13 17:16:429595 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529596 scoped_ptr<HttpTransaction> trans(
9597 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9598
9599 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9600 EXPECT_EQ(ERR_IO_PENDING, rv);
9601
9602 HostPortPair http_host_port_pair("www.example.org", 80);
9603 HttpServerProperties& http_server_properties =
9604 *session->http_server_properties();
9605 AlternativeServiceVector alternative_service_vector =
9606 http_server_properties.GetAlternativeServices(http_host_port_pair);
9607 EXPECT_TRUE(alternative_service_vector.empty());
9608
9609 EXPECT_EQ(OK, callback.WaitForResult());
9610
9611 const HttpResponseInfo* response = trans->GetResponseInfo();
9612 ASSERT_TRUE(response != NULL);
9613 ASSERT_TRUE(response->headers.get() != NULL);
9614 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9615 EXPECT_FALSE(response->was_fetched_via_spdy);
9616 EXPECT_FALSE(response->was_npn_negotiated);
9617
9618 std::string response_data;
9619 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9620 EXPECT_EQ("hello world", response_data);
9621
9622 alternative_service_vector =
9623 http_server_properties.GetAlternativeServices(http_host_port_pair);
9624 ASSERT_EQ(1u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389625 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529626 alternative_service_vector[0].protocol);
9627 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9628 EXPECT_EQ(443, alternative_service_vector[0].port);
9629}
9630
bnc4f575852015-10-14 18:35:089631TEST_P(HttpNetworkTransactionTest, ClearAlternativeServices) {
9632 session_deps_.next_protos = SpdyNextProtos();
9633 session_deps_.use_alternative_services = true;
9634
9635 // Set an alternative service for origin.
9636 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9637 HttpServerProperties& http_server_properties =
9638 *session->http_server_properties();
9639 HostPortPair http_host_port_pair("www.example.org", 80);
9640 AlternativeService alternative_service(QUIC, "", 80);
9641 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9642 http_server_properties.SetAlternativeService(
9643 http_host_port_pair, alternative_service, 1.0, expiration);
9644 AlternativeServiceVector alternative_service_vector =
9645 http_server_properties.GetAlternativeServices(http_host_port_pair);
9646 EXPECT_EQ(1u, alternative_service_vector.size());
9647
9648 // Send a clear header.
9649 MockRead data_reads[] = {
9650 MockRead("HTTP/1.1 200 OK\r\n"),
9651 MockRead("Alt-Svc: clear\r\n"),
9652 MockRead("\r\n"),
9653 MockRead("hello world"),
9654 MockRead(SYNCHRONOUS, OK),
9655 };
9656 StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
9657 session_deps_.socket_factory->AddSocketDataProvider(&data);
9658
9659 HttpRequestInfo request;
9660 request.method = "GET";
9661 request.url = GURL("http://www.example.org/");
9662 request.load_flags = 0;
9663
9664 TestCompletionCallback callback;
9665
9666 scoped_ptr<HttpTransaction> trans(
9667 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9668
9669 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9670 EXPECT_EQ(OK, callback.GetResult(rv));
9671
9672 const HttpResponseInfo* response = trans->GetResponseInfo();
9673 ASSERT_TRUE(response != nullptr);
9674 ASSERT_TRUE(response->headers.get() != nullptr);
9675 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9676 EXPECT_FALSE(response->was_fetched_via_spdy);
9677 EXPECT_FALSE(response->was_npn_negotiated);
9678
9679 std::string response_data;
9680 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9681 EXPECT_EQ("hello world", response_data);
9682
9683 alternative_service_vector =
9684 http_server_properties.GetAlternativeServices(http_host_port_pair);
9685 EXPECT_TRUE(alternative_service_vector.empty());
9686}
9687
bnc54ec34b72015-08-26 19:34:569688// Alternative Service headers must be ignored when |use_alternative_services|
9689// is false.
9690TEST_P(HttpNetworkTransactionTest, DoNotHonorAlternativeServiceHeader) {
9691 session_deps_.next_protos = SpdyNextProtos();
9692 session_deps_.use_alternative_services = false;
9693
9694 std::string alternative_service_http_header =
9695 GetAlternativeServiceHttpHeader();
9696
9697 MockRead data_reads[] = {
9698 MockRead("HTTP/1.1 200 OK\r\n"),
9699 MockRead(alternative_service_http_header.c_str()),
9700 MockRead("\r\n"),
9701 MockRead("hello world"),
9702 MockRead(SYNCHRONOUS, OK),
9703 };
9704
9705 HttpRequestInfo request;
9706 request.method = "GET";
9707 request.url = GURL("http://www.example.org/");
9708 request.load_flags = 0;
9709
9710 StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
9711
9712 session_deps_.socket_factory->AddSocketDataProvider(&data);
9713
9714 TestCompletionCallback callback;
9715
mmenkee65e7af2015-10-13 17:16:429716 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc54ec34b72015-08-26 19:34:569717 scoped_ptr<HttpTransaction> trans(
9718 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9719
9720 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9721 EXPECT_EQ(ERR_IO_PENDING, rv);
9722
9723 HostPortPair http_host_port_pair("www.example.org", 80);
9724 HttpServerProperties& http_server_properties =
9725 *session->http_server_properties();
9726 AlternativeServiceVector alternative_service_vector =
9727 http_server_properties.GetAlternativeServices(http_host_port_pair);
9728 EXPECT_TRUE(alternative_service_vector.empty());
9729
9730 EXPECT_EQ(OK, callback.WaitForResult());
9731
9732 const HttpResponseInfo* response = trans->GetResponseInfo();
9733 ASSERT_TRUE(response != nullptr);
9734 ASSERT_TRUE(response->headers.get() != nullptr);
9735 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9736 EXPECT_FALSE(response->was_fetched_via_spdy);
9737 EXPECT_FALSE(response->was_npn_negotiated);
9738
9739 std::string response_data;
9740 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9741 EXPECT_EQ("hello world", response_data);
9742
9743 alternative_service_vector =
9744 http_server_properties.GetAlternativeServices(http_host_port_pair);
9745 EXPECT_TRUE(alternative_service_vector.empty());
9746}
9747
bncc958faa2015-07-31 18:14:529748TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) {
9749 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359750 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529751
9752 MockRead data_reads[] = {
9753 MockRead("HTTP/1.1 200 OK\r\n"),
9754 MockRead("Alt-Svc: "),
9755 MockRead(GetAlternateProtocolFromParam()),
bnc44858c82015-10-16 11:57:219756 MockRead("=\"www.example.com:443\";p=\"1.0\","),
bncc958faa2015-07-31 18:14:529757 MockRead("quic=\":1234\"\r\n\r\n"),
9758 MockRead("hello world"),
9759 MockRead(SYNCHRONOUS, OK),
9760 };
9761
9762 HttpRequestInfo request;
9763 request.method = "GET";
9764 request.url = GURL("http://www.example.org/");
9765 request.load_flags = 0;
9766
9767 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9768
9769 session_deps_.socket_factory->AddSocketDataProvider(&data);
9770
9771 TestCompletionCallback callback;
9772
mmenkee65e7af2015-10-13 17:16:429773 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529774 scoped_ptr<HttpTransaction> trans(
9775 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9776
9777 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9778 EXPECT_EQ(ERR_IO_PENDING, rv);
9779
9780 HostPortPair http_host_port_pair("www.example.org", 80);
9781 HttpServerProperties& http_server_properties =
9782 *session->http_server_properties();
9783 AlternativeServiceVector alternative_service_vector =
9784 http_server_properties.GetAlternativeServices(http_host_port_pair);
9785 EXPECT_TRUE(alternative_service_vector.empty());
9786
9787 EXPECT_EQ(OK, callback.WaitForResult());
9788
9789 const HttpResponseInfo* response = trans->GetResponseInfo();
9790 ASSERT_TRUE(response != NULL);
9791 ASSERT_TRUE(response->headers.get() != NULL);
9792 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9793 EXPECT_FALSE(response->was_fetched_via_spdy);
9794 EXPECT_FALSE(response->was_npn_negotiated);
9795
9796 std::string response_data;
9797 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9798 EXPECT_EQ("hello world", response_data);
9799
9800 alternative_service_vector =
9801 http_server_properties.GetAlternativeServices(http_host_port_pair);
9802 ASSERT_EQ(2u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389803 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529804 alternative_service_vector[0].protocol);
9805 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9806 EXPECT_EQ(443, alternative_service_vector[0].port);
9807 EXPECT_EQ(QUIC, alternative_service_vector[1].protocol);
9808 EXPECT_EQ("www.example.org", alternative_service_vector[1].host);
9809 EXPECT_EQ(1234, alternative_service_vector[1].port);
9810}
9811
bnc54ec34b72015-08-26 19:34:569812// Alternate Protocol headers must be honored even if |use_alternative_services|
9813// is false.
[email protected]23e482282013-06-14 16:08:029814TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]d7599122014-05-24 03:37:239815 session_deps_.next_protos = SpdyNextProtos();
bnc54ec34b72015-08-26 19:34:569816 session_deps_.use_alternative_services = false;
[email protected]a2cb8122010-03-10 17:22:429817
[email protected]8a0fc822013-06-27 20:52:439818 std::string alternate_protocol_http_header =
9819 GetAlternateProtocolHttpHeader();
9820
[email protected]564b4912010-03-09 16:30:429821 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:529822 MockRead("HTTP/1.1 200 OK\r\n"),
9823 MockRead(alternate_protocol_http_header.c_str()),
9824 MockRead("\r\n"),
9825 MockRead("hello world"),
9826 MockRead(SYNCHRONOUS, OK),
[email protected]564b4912010-03-09 16:30:429827 };
9828
9829 HttpRequestInfo request;
9830 request.method = "GET";
bncce36dca22015-04-21 22:11:239831 request.url = GURL("http://www.example.org/");
[email protected]564b4912010-03-09 16:30:429832 request.load_flags = 0;
9833
9834 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9835
[email protected]bb88e1d32013-05-03 23:11:079836 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]564b4912010-03-09 16:30:429837
[email protected]49639fa2011-12-20 23:22:419838 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:429839
mmenkee65e7af2015-10-13 17:16:429840 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:369841 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509842 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]564b4912010-03-09 16:30:429843
[email protected]49639fa2011-12-20 23:22:419844 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:429845 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:539846
bncce36dca22015-04-21 22:11:239847 HostPortPair http_host_port_pair("www.example.org", 80);
[email protected]9801e3702014-03-07 09:33:559848 HttpServerProperties& http_server_properties =
[email protected]17291a022011-10-10 07:32:539849 *session->http_server_properties();
bncd9b132e2015-07-08 05:16:109850 AlternativeServiceVector alternative_service_vector =
9851 http_server_properties.GetAlternativeServices(http_host_port_pair);
9852 EXPECT_TRUE(alternative_service_vector.empty());
[email protected]564b4912010-03-09 16:30:429853
9854 EXPECT_EQ(OK, callback.WaitForResult());
9855
9856 const HttpResponseInfo* response = trans->GetResponseInfo();
9857 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:509858 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]564b4912010-03-09 16:30:429859 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:539860 EXPECT_FALSE(response->was_fetched_via_spdy);
9861 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:429862
9863 std::string response_data;
9864 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9865 EXPECT_EQ("hello world", response_data);
9866
bncd9b132e2015-07-08 05:16:109867 alternative_service_vector =
9868 http_server_properties.GetAlternativeServices(http_host_port_pair);
9869 ASSERT_EQ(1u, alternative_service_vector.size());
9870 EXPECT_EQ(443, alternative_service_vector[0].port);
rdsmithebb50aa2015-11-12 03:44:389871 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncd9b132e2015-07-08 05:16:109872 alternative_service_vector[0].protocol);
[email protected]564b4912010-03-09 16:30:429873}
9874
rch89c6e102015-03-18 18:56:529875TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
9876 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359877 session_deps_.use_alternative_services = true;
rch89c6e102015-03-18 18:56:529878
9879 MockRead data_reads[] = {
9880 MockRead("HTTP/1.1 200 OK\r\n"),
9881 MockRead("Alternate-Protocol: \r\n\r\n"),
9882 MockRead("hello world"),
9883 MockRead(SYNCHRONOUS, OK),
9884 };
9885
9886 HttpRequestInfo request;
9887 request.method = "GET";
bncce36dca22015-04-21 22:11:239888 request.url = GURL("http://www.example.org/");
rch89c6e102015-03-18 18:56:529889 request.load_flags = 0;
9890
9891 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9892
9893 session_deps_.socket_factory->AddSocketDataProvider(&data);
9894
9895 TestCompletionCallback callback;
9896
mmenkee65e7af2015-10-13 17:16:429897 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rch89c6e102015-03-18 18:56:529898
bncce36dca22015-04-21 22:11:239899 HostPortPair http_host_port_pair("www.example.org", 80);
rch89c6e102015-03-18 18:56:529900 HttpServerProperties& http_server_properties =
9901 *session->http_server_properties();
bnccacc0992015-03-20 20:22:229902 AlternativeService alternative_service(QUIC, "", 80);
bnc7dc7e1b42015-07-28 14:43:129903 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
9904 http_server_properties.SetAlternativeService(
9905 http_host_port_pair, alternative_service, 1.0, expiration);
bnccacc0992015-03-20 20:22:229906
bncd9b132e2015-07-08 05:16:109907 AlternativeServiceVector alternative_service_vector =
9908 http_server_properties.GetAlternativeServices(http_host_port_pair);
9909 ASSERT_EQ(1u, alternative_service_vector.size());
9910 EXPECT_EQ(QUIC, alternative_service_vector[0].protocol);
rch89c6e102015-03-18 18:56:529911
9912 scoped_ptr<HttpTransaction> trans(
9913 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9914
9915 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9916 EXPECT_EQ(ERR_IO_PENDING, rv);
9917
9918 EXPECT_EQ(OK, callback.WaitForResult());
9919
9920 const HttpResponseInfo* response = trans->GetResponseInfo();
9921 ASSERT_TRUE(response != NULL);
9922 ASSERT_TRUE(response->headers.get() != NULL);
9923 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9924 EXPECT_FALSE(response->was_fetched_via_spdy);
9925 EXPECT_FALSE(response->was_npn_negotiated);
9926
9927 std::string response_data;
9928 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9929 EXPECT_EQ("hello world", response_data);
9930
bncd9b132e2015-07-08 05:16:109931 alternative_service_vector =
9932 http_server_properties.GetAlternativeServices(http_host_port_pair);
9933 EXPECT_TRUE(alternative_service_vector.empty());
rch89c6e102015-03-18 18:56:529934}
9935
bncc958faa2015-07-31 18:14:529936TEST_P(HttpNetworkTransactionTest, AltSvcOverwritesAlternateProtocol) {
9937 session_deps_.next_protos = SpdyNextProtos();
bnc55ff9da2015-08-19 18:42:359938 session_deps_.use_alternative_services = true;
bncc958faa2015-07-31 18:14:529939
9940 std::string alternative_service_http_header =
9941 GetAlternativeServiceHttpHeader();
9942 std::string alternate_protocol_http_header = GetAlternateProtocolHttpHeader();
9943
9944 MockRead data_reads[] = {
9945 MockRead("HTTP/1.1 200 OK\r\n"),
9946 MockRead(alternative_service_http_header.c_str()),
9947 MockRead(alternate_protocol_http_header.c_str()),
9948 MockRead("\r\n"),
9949 MockRead("hello world"),
9950 MockRead(SYNCHRONOUS, OK),
9951 };
9952
9953 HttpRequestInfo request;
9954 request.method = "GET";
9955 request.url = GURL("http://www.example.org/");
9956 request.load_flags = 0;
9957
9958 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9959
9960 session_deps_.socket_factory->AddSocketDataProvider(&data);
9961
9962 TestCompletionCallback callback;
9963
mmenkee65e7af2015-10-13 17:16:429964 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529965 scoped_ptr<HttpTransaction> trans(
9966 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9967
9968 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9969 EXPECT_EQ(ERR_IO_PENDING, rv);
9970
9971 HostPortPair http_host_port_pair("www.example.org", 80);
9972 HttpServerProperties& http_server_properties =
9973 *session->http_server_properties();
9974 AlternativeServiceVector alternative_service_vector =
9975 http_server_properties.GetAlternativeServices(http_host_port_pair);
9976 EXPECT_TRUE(alternative_service_vector.empty());
9977
9978 EXPECT_EQ(OK, callback.WaitForResult());
9979
9980 const HttpResponseInfo* response = trans->GetResponseInfo();
9981 ASSERT_TRUE(response != NULL);
9982 ASSERT_TRUE(response->headers.get() != NULL);
9983 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9984 EXPECT_FALSE(response->was_fetched_via_spdy);
9985 EXPECT_FALSE(response->was_npn_negotiated);
9986
9987 std::string response_data;
9988 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9989 EXPECT_EQ("hello world", response_data);
9990
9991 alternative_service_vector =
9992 http_server_properties.GetAlternativeServices(http_host_port_pair);
9993 ASSERT_EQ(1u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389994 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529995 alternative_service_vector[0].protocol);
9996 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9997 EXPECT_EQ(443, alternative_service_vector[0].port);
9998}
9999
bnc54ec34b72015-08-26 19:34:5610000// When |use_alternative_services| is false, do not observe alternative service
10001// entries that point to a different host.
10002TEST_P(HttpNetworkTransactionTest, DisableAlternativeServiceToDifferentHost) {
10003 session_deps_.use_alternative_services = false;
10004
10005 HttpRequestInfo request;
10006 request.method = "GET";
10007 request.url = GURL("http://www.example.org/");
10008 request.load_flags = 0;
10009
10010 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
10011 StaticSocketDataProvider first_data;
10012 first_data.set_connect_data(mock_connect);
10013 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
10014
10015 MockRead data_reads[] = {
10016 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
10017 MockRead(ASYNC, OK),
10018 };
10019 StaticSocketDataProvider second_data(data_reads, arraysize(data_reads),
10020 nullptr, 0);
10021 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
10022
mmenkee65e7af2015-10-13 17:16:4210023 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc54ec34b72015-08-26 19:34:5610024
10025 base::WeakPtr<HttpServerProperties> http_server_properties =
10026 session->http_server_properties();
10027 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810028 AlternateProtocolFromNextProto(GetProtocol()), "different.example.org",
10029 80);
bnc54ec34b72015-08-26 19:34:5610030 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10031 http_server_properties->SetAlternativeService(
10032 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
10033
10034 scoped_ptr<HttpTransaction> trans(
10035 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10036 TestCompletionCallback callback;
10037
10038 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10039 // The connetion to origin was refused, and the alternative service should not
10040 // be used (even though mock data are there), therefore the request should
10041 // fail.
10042 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.GetResult(rv));
10043}
10044
zhongyi48704c182015-12-07 07:52:0210045TEST_P(HttpNetworkTransactionTest, IdentifyQuicBroken) {
10046 HostPortPair origin("origin.example.org", 443);
10047 HostPortPair alternative("alternative.example.org", 443);
10048 std::string origin_url = "https://origin.example.org:443";
10049 std::string alternative_url = "https://alternative.example.org:443";
10050
10051 // Negotiate HTTP/1.1 with alternative.example.org.
10052 SSLSocketDataProvider ssl(ASYNC, OK);
10053 ssl.SetNextProto(kProtoHTTP11);
10054 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10055
10056 // HTTP/1.1 data for request.
10057 MockWrite http_writes[] = {
10058 MockWrite("GET / HTTP/1.1\r\n"
10059 "Host: alternative.example.org\r\n"
10060 "Connection: keep-alive\r\n\r\n"),
10061 };
10062
10063 MockRead http_reads[] = {
10064 MockRead("HTTP/1.1 200 OK\r\n"
10065 "Content-Type: text/html; charset=iso-8859-1\r\n"
10066 "Content-Length: 40\r\n\r\n"
10067 "first HTTP/1.1 response from alternative"),
10068 };
10069 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
10070 http_writes, arraysize(http_writes));
10071 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
10072
10073 StaticSocketDataProvider data_refused;
10074 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
10075 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
10076
10077 // Set up a QUIC alternative service for origin.
10078 session_deps_.use_alternative_services = true;
10079 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10080 base::WeakPtr<HttpServerProperties> http_server_properties =
10081 session->http_server_properties();
10082 AlternativeService alternative_service(QUIC, alternative);
10083 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10084 http_server_properties->SetAlternativeService(origin, alternative_service,
10085 1.0, expiration);
10086 // Mark the QUIC alternative service as broken.
10087 http_server_properties->MarkAlternativeServiceBroken(alternative_service);
10088
10089 scoped_ptr<HttpTransaction> trans(
10090 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10091 HttpRequestInfo request;
10092 request.method = "GET";
10093 request.url = GURL(origin_url);
10094 request.load_flags = 0;
10095 TestCompletionCallback callback;
10096 NetErrorDetails details;
10097 EXPECT_FALSE(details.quic_broken);
10098
10099 trans->Start(&request, callback.callback(), BoundNetLog());
10100 trans->PopulateNetErrorDetails(&details);
10101 EXPECT_TRUE(details.quic_broken);
10102}
10103
10104TEST_P(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
10105 HostPortPair origin("origin.example.org", 443);
10106 HostPortPair alternative1("alternative1.example.org", 443);
10107 HostPortPair alternative2("alternative2.example.org", 443);
10108 std::string origin_url = "https://origin.example.org:443";
10109 std::string alternative_url1 = "https://alternative1.example.org:443";
10110 std::string alternative_url2 = "https://alternative2.example.org:443";
10111
10112 // Negotiate HTTP/1.1 with alternative1.example.org.
10113 SSLSocketDataProvider ssl(ASYNC, OK);
10114 ssl.SetNextProto(kProtoHTTP11);
10115 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10116
10117 // HTTP/1.1 data for request.
10118 MockWrite http_writes[] = {
10119 MockWrite("GET / HTTP/1.1\r\n"
10120 "Host: alternative1.example.org\r\n"
10121 "Connection: keep-alive\r\n\r\n"),
10122 };
10123
10124 MockRead http_reads[] = {
10125 MockRead("HTTP/1.1 200 OK\r\n"
10126 "Content-Type: text/html; charset=iso-8859-1\r\n"
10127 "Content-Length: 40\r\n\r\n"
10128 "first HTTP/1.1 response from alternative1"),
10129 };
10130 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
10131 http_writes, arraysize(http_writes));
10132 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
10133
10134 StaticSocketDataProvider data_refused;
10135 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
10136 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
10137
10138 session_deps_.use_alternative_services = true;
10139 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10140 base::WeakPtr<HttpServerProperties> http_server_properties =
10141 session->http_server_properties();
10142
10143 // Set up two QUIC alternative services for origin.
10144 AlternativeServiceInfoVector alternative_service_info_vector;
10145 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10146
10147 AlternativeService alternative_service1(QUIC, alternative1);
10148 AlternativeServiceInfo alternative_service_info1(alternative_service1, 1.0,
10149 expiration);
10150 alternative_service_info_vector.push_back(alternative_service_info1);
10151 AlternativeService alternative_service2(QUIC, alternative2);
10152 AlternativeServiceInfo alternative_service_info2(alternative_service2, 1.0,
10153 expiration);
10154 alternative_service_info_vector.push_back(alternative_service_info2);
10155
10156 http_server_properties->SetAlternativeServices(
10157 origin, alternative_service_info_vector);
10158
10159 // Mark one of the QUIC alternative service as broken.
10160 http_server_properties->MarkAlternativeServiceBroken(alternative_service1);
10161
10162 const AlternativeServiceVector alternative_service_vector =
10163 http_server_properties->GetAlternativeServices(origin);
10164
10165 scoped_ptr<HttpTransaction> trans(
10166 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10167 HttpRequestInfo request;
10168 request.method = "GET";
10169 request.url = GURL(origin_url);
10170 request.load_flags = 0;
10171 TestCompletionCallback callback;
10172 NetErrorDetails details;
10173 EXPECT_FALSE(details.quic_broken);
10174
10175 trans->Start(&request, callback.callback(), BoundNetLog());
10176 trans->PopulateNetErrorDetails(&details);
10177 EXPECT_FALSE(details.quic_broken);
10178}
10179
[email protected]23e482282013-06-14 16:08:0210180TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310181 MarkBrokenAlternateProtocolAndFallback) {
bnc55ff9da2015-08-19 18:42:3510182 session_deps_.use_alternative_services = true;
[email protected]564b4912010-03-09 16:30:4210183
10184 HttpRequestInfo request;
10185 request.method = "GET";
bncce36dca22015-04-21 22:11:2310186 request.url = GURL("http://www.example.org/");
[email protected]564b4912010-03-09 16:30:4210187 request.load_flags = 0;
10188
[email protected]d973e99a2012-02-17 21:02:3610189 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4210190 StaticSocketDataProvider first_data;
10191 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710192 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]564b4912010-03-09 16:30:4210193
10194 MockRead data_reads[] = {
10195 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10196 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610197 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4210198 };
10199 StaticSocketDataProvider second_data(
10200 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710201 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4210202
mmenkee65e7af2015-10-13 17:16:4210203 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4210204
[email protected]30d4c022013-07-18 22:58:1610205 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310206 session->http_server_properties();
bnc8445b3002015-03-13 01:57:0910207 const HostPortPair host_port_pair = HostPortPair::FromURL(request.url);
[email protected]3912662a32011-10-04 00:51:1110208 // Port must be < 1024, or the header will be ignored (since initial port was
10209 // port 80 (another restricted port).
bncd9b132e2015-07-08 05:16:1010210 const AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810211 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bncd9b132e2015-07-08 05:16:1010212 666); // Port is ignored by MockConnect anyway.
bnc7dc7e1b42015-07-28 14:43:1210213 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10214 http_server_properties->SetAlternativeService(
10215 host_port_pair, alternative_service, 1.0, expiration);
[email protected]564b4912010-03-09 16:30:4210216
[email protected]262eec82013-03-19 21:01:3610217 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010218 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110219 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4210220
[email protected]49639fa2011-12-20 23:22:4110221 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:4210222 EXPECT_EQ(ERR_IO_PENDING, rv);
10223 EXPECT_EQ(OK, callback.WaitForResult());
10224
10225 const HttpResponseInfo* response = trans->GetResponseInfo();
10226 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010227 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]564b4912010-03-09 16:30:4210228 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10229
10230 std::string response_data;
10231 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10232 EXPECT_EQ("hello world", response_data);
10233
bncd9b132e2015-07-08 05:16:1010234 const AlternativeServiceVector alternative_service_vector =
10235 http_server_properties->GetAlternativeServices(host_port_pair);
10236 ASSERT_EQ(1u, alternative_service_vector.size());
10237 EXPECT_EQ(alternative_service, alternative_service_vector[0]);
10238 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
10239 alternative_service_vector[0]));
[email protected]564b4912010-03-09 16:30:4210240}
10241
bnc55ff9da2015-08-19 18:42:3510242// Ensure that we are not allowed to redirect traffic via an alternate protocol
10243// to an unrestricted (port >= 1024) when the original traffic was on a
10244// restricted port (port < 1024). Ensure that we can redirect in all other
10245// cases.
[email protected]23e482282013-06-14 16:08:0210246TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310247 AlternateProtocolPortRestrictedBlocked) {
bnc55ff9da2015-08-19 18:42:3510248 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110249
10250 HttpRequestInfo restricted_port_request;
10251 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310252 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1110253 restricted_port_request.load_flags = 0;
10254
[email protected]d973e99a2012-02-17 21:02:3610255 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110256 StaticSocketDataProvider first_data;
10257 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710258 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110259
10260 MockRead data_reads[] = {
10261 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10262 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610263 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110264 };
10265 StaticSocketDataProvider second_data(
10266 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710267 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110268
mmenkee65e7af2015-10-13 17:16:4210269 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110270
[email protected]30d4c022013-07-18 22:58:1610271 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310272 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110273 const int kUnrestrictedAlternatePort = 1024;
bnccacc0992015-03-20 20:22:2210274 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810275 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210276 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210277 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210278 http_server_properties->SetAlternativeService(
10279 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210280 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110281
[email protected]262eec82013-03-19 21:01:3610282 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010283 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110284 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110285
[email protected]49639fa2011-12-20 23:22:4110286 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:3610287 &restricted_port_request,
10288 callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110289 EXPECT_EQ(ERR_IO_PENDING, rv);
10290 // Invalid change to unrestricted port should fail.
10291 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
[email protected]c54c6962013-02-01 04:53:1910292}
[email protected]3912662a32011-10-04 00:51:1110293
bnc55ff9da2015-08-19 18:42:3510294// Ensure that we are allowed to redirect traffic via an alternate protocol to
10295// an unrestricted (port >= 1024) when the original traffic was on a restricted
10296// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
[email protected]23e482282013-06-14 16:08:0210297TEST_P(HttpNetworkTransactionTest,
[email protected]c54c6962013-02-01 04:53:1910298 AlternateProtocolPortRestrictedPermitted) {
bnc55ff9da2015-08-19 18:42:3510299 session_deps_.use_alternative_services = true;
[email protected]bb88e1d32013-05-03 23:11:0710300 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1910301
10302 HttpRequestInfo restricted_port_request;
10303 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310304 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1910305 restricted_port_request.load_flags = 0;
10306
10307 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
10308 StaticSocketDataProvider first_data;
10309 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710310 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1910311
10312 MockRead data_reads[] = {
10313 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10314 MockRead("hello world"),
10315 MockRead(ASYNC, OK),
10316 };
10317 StaticSocketDataProvider second_data(
10318 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710319 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]c54c6962013-02-01 04:53:1910320
mmenkee65e7af2015-10-13 17:16:4210321 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1910322
[email protected]30d4c022013-07-18 22:58:1610323 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]c54c6962013-02-01 04:53:1910324 session->http_server_properties();
10325 const int kUnrestrictedAlternatePort = 1024;
bnccacc0992015-03-20 20:22:2210326 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810327 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210328 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210329 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210330 http_server_properties->SetAlternativeService(
10331 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210332 1.0, expiration);
[email protected]c54c6962013-02-01 04:53:1910333
[email protected]262eec82013-03-19 21:01:3610334 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010335 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]c54c6962013-02-01 04:53:1910336 TestCompletionCallback callback;
10337
10338 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
[email protected]262eec82013-03-19 21:01:3610339 &restricted_port_request,
10340 callback.callback(), BoundNetLog()));
[email protected]c54c6962013-02-01 04:53:1910341 // Change to unrestricted port should succeed.
10342 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110343}
10344
bnc55ff9da2015-08-19 18:42:3510345// Ensure that we are not allowed to redirect traffic via an alternate protocol
10346// to an unrestricted (port >= 1024) when the original traffic was on a
10347// restricted port (port < 1024). Ensure that we can redirect in all other
10348// cases.
[email protected]23e482282013-06-14 16:08:0210349TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310350 AlternateProtocolPortRestrictedAllowed) {
bnc55ff9da2015-08-19 18:42:3510351 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110352
10353 HttpRequestInfo restricted_port_request;
10354 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310355 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1110356 restricted_port_request.load_flags = 0;
10357
[email protected]d973e99a2012-02-17 21:02:3610358 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110359 StaticSocketDataProvider first_data;
10360 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710361 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110362
10363 MockRead data_reads[] = {
10364 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10365 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610366 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110367 };
10368 StaticSocketDataProvider second_data(
10369 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710370 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110371
mmenkee65e7af2015-10-13 17:16:4210372 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110373
[email protected]30d4c022013-07-18 22:58:1610374 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310375 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110376 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210377 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810378 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210379 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210380 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210381 http_server_properties->SetAlternativeService(
10382 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210383 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110384
[email protected]262eec82013-03-19 21:01:3610385 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010386 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110387 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110388
[email protected]49639fa2011-12-20 23:22:4110389 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:3610390 &restricted_port_request,
10391 callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110392 EXPECT_EQ(ERR_IO_PENDING, rv);
10393 // Valid change to restricted port should pass.
10394 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110395}
10396
bnc55ff9da2015-08-19 18:42:3510397// Ensure that we are not allowed to redirect traffic via an alternate protocol
10398// to an unrestricted (port >= 1024) when the original traffic was on a
10399// restricted port (port < 1024). Ensure that we can redirect in all other
10400// cases.
[email protected]23e482282013-06-14 16:08:0210401TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310402 AlternateProtocolPortUnrestrictedAllowed1) {
bnc55ff9da2015-08-19 18:42:3510403 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110404
10405 HttpRequestInfo unrestricted_port_request;
10406 unrestricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310407 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110408 unrestricted_port_request.load_flags = 0;
10409
[email protected]d973e99a2012-02-17 21:02:3610410 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110411 StaticSocketDataProvider first_data;
10412 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710413 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110414
10415 MockRead data_reads[] = {
10416 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10417 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610418 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110419 };
10420 StaticSocketDataProvider second_data(
10421 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710422 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110423
mmenkee65e7af2015-10-13 17:16:4210424 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110425
[email protected]30d4c022013-07-18 22:58:1610426 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310427 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110428 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210429 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810430 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210431 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210432 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210433 http_server_properties->SetAlternativeService(
10434 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210435 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110436
[email protected]262eec82013-03-19 21:01:3610437 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010438 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110439 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110440
[email protected]49639fa2011-12-20 23:22:4110441 int rv = trans->Start(
10442 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110443 EXPECT_EQ(ERR_IO_PENDING, rv);
10444 // Valid change to restricted port should pass.
10445 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110446}
10447
bnc55ff9da2015-08-19 18:42:3510448// Ensure that we are not allowed to redirect traffic via an alternate protocol
10449// to an unrestricted (port >= 1024) when the original traffic was on a
10450// restricted port (port < 1024). Ensure that we can redirect in all other
10451// cases.
[email protected]23e482282013-06-14 16:08:0210452TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310453 AlternateProtocolPortUnrestrictedAllowed2) {
bnc55ff9da2015-08-19 18:42:3510454 session_deps_.use_alternative_services = true;
[email protected]3912662a32011-10-04 00:51:1110455
10456 HttpRequestInfo unrestricted_port_request;
10457 unrestricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310458 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110459 unrestricted_port_request.load_flags = 0;
10460
[email protected]d973e99a2012-02-17 21:02:3610461 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110462 StaticSocketDataProvider first_data;
10463 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710464 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110465
10466 MockRead data_reads[] = {
10467 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10468 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610469 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110470 };
10471 StaticSocketDataProvider second_data(
10472 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710473 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110474
mmenkee65e7af2015-10-13 17:16:4210475 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110476
[email protected]30d4c022013-07-18 22:58:1610477 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310478 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2210479 const int kUnrestrictedAlternatePort = 1025;
bnccacc0992015-03-20 20:22:2210480 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810481 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210482 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210483 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210484 http_server_properties->SetAlternativeService(
10485 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
bnc7dc7e1b42015-07-28 14:43:1210486 1.0, expiration);
[email protected]3912662a32011-10-04 00:51:1110487
[email protected]262eec82013-03-19 21:01:3610488 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010489 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110490 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110491
[email protected]49639fa2011-12-20 23:22:4110492 int rv = trans->Start(
10493 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110494 EXPECT_EQ(ERR_IO_PENDING, rv);
10495 // Valid change to an unrestricted port should pass.
10496 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110497}
10498
bnc55ff9da2015-08-19 18:42:3510499// Ensure that we are not allowed to redirect traffic via an alternate protocol
10500// to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
10501// once the alternate protocol request fails.
[email protected]d7599122014-05-24 03:37:2310502TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
bnc55ff9da2015-08-19 18:42:3510503 session_deps_.use_alternative_services = true;
[email protected]eb6234e2012-01-19 01:50:0210504
10505 HttpRequestInfo request;
10506 request.method = "GET";
bncce36dca22015-04-21 22:11:2310507 request.url = GURL("http://www.example.org/");
[email protected]eb6234e2012-01-19 01:50:0210508 request.load_flags = 0;
10509
10510 // The alternate protocol request will error out before we attempt to connect,
10511 // so only the standard HTTP request will try to connect.
10512 MockRead data_reads[] = {
10513 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10514 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610515 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0210516 };
10517 StaticSocketDataProvider data(
10518 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710519 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0210520
mmenkee65e7af2015-10-13 17:16:4210521 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0210522
[email protected]30d4c022013-07-18 22:58:1610523 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0210524 session->http_server_properties();
10525 const int kUnsafePort = 7;
bnccacc0992015-03-20 20:22:2210526 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810527 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210528 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1210529 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210530 http_server_properties->SetAlternativeService(
bnc7dc7e1b42015-07-28 14:43:1210531 HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
[email protected]eb6234e2012-01-19 01:50:0210532
[email protected]262eec82013-03-19 21:01:3610533 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010534 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]eb6234e2012-01-19 01:50:0210535 TestCompletionCallback callback;
10536
10537 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10538 EXPECT_EQ(ERR_IO_PENDING, rv);
10539 // The HTTP request should succeed.
10540 EXPECT_EQ(OK, callback.WaitForResult());
10541
[email protected]eb6234e2012-01-19 01:50:0210542 const HttpResponseInfo* response = trans->GetResponseInfo();
10543 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010544 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]eb6234e2012-01-19 01:50:0210545 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10546
10547 std::string response_data;
10548 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10549 EXPECT_EQ("hello world", response_data);
10550}
10551
[email protected]23e482282013-06-14 16:08:0210552TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510553 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310554 session_deps_.next_protos = SpdyNextProtos();
[email protected]2ff8b312010-04-26 22:20:5410555
10556 HttpRequestInfo request;
10557 request.method = "GET";
bncce36dca22015-04-21 22:11:2310558 request.url = GURL("http://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5410559 request.load_flags = 0;
10560
[email protected]8a0fc822013-06-27 20:52:4310561 std::string alternate_protocol_http_header =
10562 GetAlternateProtocolHttpHeader();
10563
[email protected]2ff8b312010-04-26 22:20:5410564 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210565 MockRead("HTTP/1.1 200 OK\r\n"),
10566 MockRead(alternate_protocol_http_header.c_str()),
10567 MockRead("\r\n"),
10568 MockRead("hello world"),
10569 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10570 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5410571
10572 StaticSocketDataProvider first_transaction(
10573 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710574 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2ff8b312010-04-26 22:20:5410575
[email protected]8ddf8322012-02-23 18:08:0610576 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810577 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310578 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10579 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710580 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2ff8b312010-04-26 22:20:5410581
[email protected]cdf8f7e72013-05-23 10:56:4610582 scoped_ptr<SpdyFrame> req(
10583 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1310584 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]2ff8b312010-04-26 22:20:5410585
[email protected]23e482282013-06-14 16:08:0210586 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10587 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5410588 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310589 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5410590 };
10591
rch8e6c6c42015-05-01 14:05:1310592 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10593 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710594 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5410595
[email protected]d973e99a2012-02-17 21:02:3610596 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510597 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10598 NULL, 0, NULL, 0);
10599 hanging_non_alternate_protocol_socket.set_connect_data(
10600 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710601 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510602 &hanging_non_alternate_protocol_socket);
10603
[email protected]49639fa2011-12-20 23:22:4110604 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5410605
mmenkee65e7af2015-10-13 17:16:4210606 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610607 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010608 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410609
[email protected]49639fa2011-12-20 23:22:4110610 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410611 EXPECT_EQ(ERR_IO_PENDING, rv);
10612 EXPECT_EQ(OK, callback.WaitForResult());
10613
10614 const HttpResponseInfo* response = trans->GetResponseInfo();
10615 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010616 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5410617 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10618
10619 std::string response_data;
10620 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10621 EXPECT_EQ("hello world", response_data);
10622
[email protected]90499482013-06-01 00:39:5010623 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410624
[email protected]49639fa2011-12-20 23:22:4110625 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410626 EXPECT_EQ(ERR_IO_PENDING, rv);
10627 EXPECT_EQ(OK, callback.WaitForResult());
10628
10629 response = trans->GetResponseInfo();
10630 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010631 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210632 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310633 EXPECT_TRUE(response->was_fetched_via_spdy);
10634 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5410635
10636 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10637 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5410638}
10639
[email protected]23e482282013-06-14 16:08:0210640TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
bnc55ff9da2015-08-19 18:42:3510641 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310642 session_deps_.next_protos = SpdyNextProtos();
[email protected]2d6728692011-03-12 01:39:5510643
10644 HttpRequestInfo request;
10645 request.method = "GET";
bncce36dca22015-04-21 22:11:2310646 request.url = GURL("http://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510647 request.load_flags = 0;
10648
[email protected]8a0fc822013-06-27 20:52:4310649 std::string alternate_protocol_http_header =
10650 GetAlternateProtocolHttpHeader();
10651
[email protected]2d6728692011-03-12 01:39:5510652 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210653 MockRead("HTTP/1.1 200 OK\r\n"),
10654 MockRead(alternate_protocol_http_header.c_str()),
10655 MockRead("\r\n"),
10656 MockRead("hello world"),
10657 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10658 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510659 };
10660
10661 StaticSocketDataProvider first_transaction(
10662 data_reads, arraysize(data_reads), NULL, 0);
10663 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
[email protected]bb88e1d32013-05-03 23:11:0710664 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510665
[email protected]d973e99a2012-02-17 21:02:3610666 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
mmenkecc2298e2015-12-07 18:20:1810667 StaticSocketDataProvider hanging_socket1(NULL, 0, NULL, 0);
10668 hanging_socket1.set_connect_data(never_finishing_connect);
[email protected]2d6728692011-03-12 01:39:5510669 // Socket 2 and 3 are the hanging Alternate-Protocol and
10670 // non-Alternate-Protocol jobs from the 2nd transaction.
mmenkecc2298e2015-12-07 18:20:1810671 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
10672
10673 StaticSocketDataProvider hanging_socket2(NULL, 0, NULL, 0);
10674 hanging_socket2.set_connect_data(never_finishing_connect);
10675 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5510676
[email protected]8ddf8322012-02-23 18:08:0610677 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810678 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310679 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10680 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710681 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510682
[email protected]cdf8f7e72013-05-23 10:56:4610683 scoped_ptr<SpdyFrame> req1(
10684 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10685 scoped_ptr<SpdyFrame> req2(
10686 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]2d6728692011-03-12 01:39:5510687 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1310688 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
[email protected]2d6728692011-03-12 01:39:5510689 };
[email protected]23e482282013-06-14 16:08:0210690 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10691 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
10692 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10693 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5510694 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310695 CreateMockRead(*resp1, 2),
10696 CreateMockRead(*data1, 3),
10697 CreateMockRead(*resp2, 4),
10698 CreateMockRead(*data2, 5),
10699 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5510700 };
10701
rch8e6c6c42015-05-01 14:05:1310702 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10703 arraysize(spdy_writes));
[email protected]2d6728692011-03-12 01:39:5510704 // Socket 4 is the successful Alternate-Protocol for transaction 3.
[email protected]bb88e1d32013-05-03 23:11:0710705 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5510706
10707 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
mmenkecc2298e2015-12-07 18:20:1810708 StaticSocketDataProvider hanging_socket3(NULL, 0, NULL, 0);
10709 hanging_socket3.set_connect_data(never_finishing_connect);
10710 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5510711
mmenkee65e7af2015-10-13 17:16:4210712 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4110713 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5010714 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5510715
[email protected]49639fa2011-12-20 23:22:4110716 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510717 EXPECT_EQ(ERR_IO_PENDING, rv);
10718 EXPECT_EQ(OK, callback1.WaitForResult());
10719
10720 const HttpResponseInfo* response = trans1.GetResponseInfo();
10721 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010722 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510723 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10724
10725 std::string response_data;
10726 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10727 EXPECT_EQ("hello world", response_data);
10728
[email protected]49639fa2011-12-20 23:22:4110729 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5010730 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110731 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510732 EXPECT_EQ(ERR_IO_PENDING, rv);
10733
[email protected]49639fa2011-12-20 23:22:4110734 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5010735 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110736 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510737 EXPECT_EQ(ERR_IO_PENDING, rv);
10738
10739 EXPECT_EQ(OK, callback2.WaitForResult());
10740 EXPECT_EQ(OK, callback3.WaitForResult());
10741
10742 response = trans2.GetResponseInfo();
10743 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010744 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210745 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5510746 EXPECT_TRUE(response->was_fetched_via_spdy);
10747 EXPECT_TRUE(response->was_npn_negotiated);
10748 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10749 EXPECT_EQ("hello!", response_data);
10750
10751 response = trans3.GetResponseInfo();
10752 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010753 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210754 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5510755 EXPECT_TRUE(response->was_fetched_via_spdy);
10756 EXPECT_TRUE(response->was_npn_negotiated);
10757 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
10758 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5510759}
10760
[email protected]23e482282013-06-14 16:08:0210761TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510762 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310763 session_deps_.next_protos = SpdyNextProtos();
[email protected]2d6728692011-03-12 01:39:5510764
10765 HttpRequestInfo request;
10766 request.method = "GET";
bncce36dca22015-04-21 22:11:2310767 request.url = GURL("http://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510768 request.load_flags = 0;
10769
[email protected]8a0fc822013-06-27 20:52:4310770 std::string alternate_protocol_http_header =
10771 GetAlternateProtocolHttpHeader();
10772
[email protected]2d6728692011-03-12 01:39:5510773 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210774 MockRead("HTTP/1.1 200 OK\r\n"),
10775 MockRead(alternate_protocol_http_header.c_str()),
10776 MockRead("\r\n"),
10777 MockRead("hello world"),
10778 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10779 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510780 };
10781
10782 StaticSocketDataProvider first_transaction(
10783 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710784 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510785
[email protected]8ddf8322012-02-23 18:08:0610786 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810787 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0710788 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510789
[email protected]d973e99a2012-02-17 21:02:3610790 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510791 StaticSocketDataProvider hanging_alternate_protocol_socket(
10792 NULL, 0, NULL, 0);
10793 hanging_alternate_protocol_socket.set_connect_data(
10794 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710795 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510796 &hanging_alternate_protocol_socket);
10797
10798 // 2nd request is just a copy of the first one, over HTTP again.
mmenkecc2298e2015-12-07 18:20:1810799 StaticSocketDataProvider second_transaction(data_reads, arraysize(data_reads),
10800 NULL, 0);
10801 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
[email protected]2d6728692011-03-12 01:39:5510802
[email protected]49639fa2011-12-20 23:22:4110803 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5510804
mmenkee65e7af2015-10-13 17:16:4210805 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610806 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010807 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510808
[email protected]49639fa2011-12-20 23:22:4110809 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510810 EXPECT_EQ(ERR_IO_PENDING, rv);
10811 EXPECT_EQ(OK, callback.WaitForResult());
10812
10813 const HttpResponseInfo* response = trans->GetResponseInfo();
10814 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010815 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510816 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10817
10818 std::string response_data;
10819 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10820 EXPECT_EQ("hello world", response_data);
10821
[email protected]90499482013-06-01 00:39:5010822 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510823
[email protected]49639fa2011-12-20 23:22:4110824 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510825 EXPECT_EQ(ERR_IO_PENDING, rv);
10826 EXPECT_EQ(OK, callback.WaitForResult());
10827
10828 response = trans->GetResponseInfo();
10829 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010830 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510831 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10832 EXPECT_FALSE(response->was_fetched_via_spdy);
10833 EXPECT_FALSE(response->was_npn_negotiated);
10834
10835 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10836 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5510837}
10838
[email protected]631f1322010-04-30 17:59:1110839class CapturingProxyResolver : public ProxyResolver {
10840 public:
sammce90c9212015-05-27 23:43:3510841 CapturingProxyResolver() {}
dchengb03027d2014-10-21 12:00:2010842 ~CapturingProxyResolver() override {}
[email protected]631f1322010-04-30 17:59:1110843
dchengb03027d2014-10-21 12:00:2010844 int GetProxyForURL(const GURL& url,
10845 ProxyInfo* results,
10846 const CompletionCallback& callback,
10847 RequestHandle* request,
10848 const BoundNetLog& net_log) override {
[email protected]fae7669f2010-08-02 21:49:4010849 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
10850 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:4210851 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:1110852 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:4210853 return OK;
[email protected]631f1322010-04-30 17:59:1110854 }
10855
dchengb03027d2014-10-21 12:00:2010856 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
[email protected]631f1322010-04-30 17:59:1110857
dchengb03027d2014-10-21 12:00:2010858 LoadState GetLoadState(RequestHandle request) const override {
[email protected]f2c971f2011-11-08 00:33:1710859 NOTREACHED();
10860 return LOAD_STATE_IDLE;
10861 }
10862
[email protected]24476402010-07-20 20:55:1710863 const std::vector<GURL>& resolved() const { return resolved_; }
10864
10865 private:
[email protected]631f1322010-04-30 17:59:1110866 std::vector<GURL> resolved_;
10867
10868 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
10869};
10870
sammce64b2362015-04-29 03:50:2310871class CapturingProxyResolverFactory : public ProxyResolverFactory {
10872 public:
10873 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
10874 : ProxyResolverFactory(false), resolver_(resolver) {}
10875
10876 int CreateProxyResolver(
10877 const scoped_refptr<ProxyResolverScriptData>& pac_script,
10878 scoped_ptr<ProxyResolver>* resolver,
10879 const net::CompletionCallback& callback,
10880 scoped_ptr<Request>* request) override {
10881 resolver->reset(new ForwardingProxyResolver(resolver_));
10882 return OK;
10883 }
10884
10885 private:
10886 ProxyResolver* resolver_;
10887};
10888
[email protected]23e482282013-06-14 16:08:0210889TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310890 UseAlternateProtocolForTunneledNpnSpdy) {
bnc55ff9da2015-08-19 18:42:3510891 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2310892 session_deps_.next_protos = SpdyNextProtos();
[email protected]631f1322010-04-30 17:59:1110893
10894 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4210895 proxy_config.set_auto_detect(true);
10896 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1110897
sammc5dd160c2015-04-02 02:43:1310898 CapturingProxyResolver capturing_proxy_resolver;
[email protected]bb88e1d32013-05-03 23:11:0710899 session_deps_.proxy_service.reset(new ProxyService(
csharrisonb7e3a082015-09-22 19:13:0410900 make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)),
sammc5dd160c2015-04-02 02:43:1310901 make_scoped_ptr(
sammce64b2362015-04-29 03:50:2310902 new CapturingProxyResolverFactory(&capturing_proxy_resolver)),
[email protected]66761b952010-06-25 21:30:3810903 NULL));
vishal.b62985ca92015-04-17 08:45:5110904 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710905 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1110906
10907 HttpRequestInfo request;
10908 request.method = "GET";
bncce36dca22015-04-21 22:11:2310909 request.url = GURL("http://www.example.org/");
[email protected]631f1322010-04-30 17:59:1110910 request.load_flags = 0;
10911
[email protected]8a0fc822013-06-27 20:52:4310912 std::string alternate_protocol_http_header =
10913 GetAlternateProtocolHttpHeader();
10914
[email protected]631f1322010-04-30 17:59:1110915 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210916 MockRead("HTTP/1.1 200 OK\r\n"),
10917 MockRead(alternate_protocol_http_header.c_str()),
10918 MockRead("\r\n"),
10919 MockRead("hello world"),
10920 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10921 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1110922 };
10923
10924 StaticSocketDataProvider first_transaction(
10925 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710926 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]631f1322010-04-30 17:59:1110927
[email protected]8ddf8322012-02-23 18:08:0610928 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810929 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310930 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10931 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710932 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]631f1322010-04-30 17:59:1110933
[email protected]cdf8f7e72013-05-23 10:56:4610934 scoped_ptr<SpdyFrame> req(
10935 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]631f1322010-04-30 17:59:1110936 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1310937 MockWrite(ASYNC, 0,
10938 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1710939 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1310940 "Proxy-Connection: keep-alive\r\n\r\n"),
10941 CreateMockWrite(*req, 2),
[email protected]631f1322010-04-30 17:59:1110942 };
10943
[email protected]d911f1b2010-05-05 22:39:4210944 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10945
[email protected]23e482282013-06-14 16:08:0210946 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10947 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:1110948 MockRead spdy_reads[] = {
mmenkee24011922015-12-17 22:12:5910949 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(*resp.get(), 3),
10950 CreateMockRead(*data.get(), 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1110951 };
10952
rch8e6c6c42015-05-01 14:05:1310953 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10954 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710955 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1110956
[email protected]d973e99a2012-02-17 21:02:3610957 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510958 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10959 NULL, 0, NULL, 0);
10960 hanging_non_alternate_protocol_socket.set_connect_data(
10961 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710962 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510963 &hanging_non_alternate_protocol_socket);
10964
[email protected]49639fa2011-12-20 23:22:4110965 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1110966
mmenkee65e7af2015-10-13 17:16:4210967 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610968 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010969 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1110970
[email protected]49639fa2011-12-20 23:22:4110971 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:1110972 EXPECT_EQ(ERR_IO_PENDING, rv);
10973 EXPECT_EQ(OK, callback.WaitForResult());
10974
10975 const HttpResponseInfo* response = trans->GetResponseInfo();
10976 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010977 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]631f1322010-04-30 17:59:1110978 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310979 EXPECT_FALSE(response->was_fetched_via_spdy);
10980 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:1110981
10982 std::string response_data;
10983 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10984 EXPECT_EQ("hello world", response_data);
10985
[email protected]90499482013-06-01 00:39:5010986 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1110987
[email protected]49639fa2011-12-20 23:22:4110988 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:1110989 EXPECT_EQ(ERR_IO_PENDING, rv);
10990 EXPECT_EQ(OK, callback.WaitForResult());
10991
10992 response = trans->GetResponseInfo();
10993 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010994 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210995 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310996 EXPECT_TRUE(response->was_fetched_via_spdy);
10997 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:1110998
10999 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11000 EXPECT_EQ("hello!", response_data);
sammc5dd160c2015-04-02 02:43:1311001 ASSERT_EQ(3u, capturing_proxy_resolver.resolved().size());
bncce36dca22015-04-21 22:11:2311002 EXPECT_EQ("http://www.example.org/",
sammc5dd160c2015-04-02 02:43:1311003 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2311004 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1311005 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1111006
[email protected]029c83b62013-01-24 05:28:2011007 LoadTimingInfo load_timing_info;
11008 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11009 TestLoadTimingNotReusedWithPac(load_timing_info,
11010 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1111011}
[email protected]631f1322010-04-30 17:59:1111012
[email protected]23e482282013-06-14 16:08:0211013TEST_P(HttpNetworkTransactionTest,
[email protected]2ff8b312010-04-26 22:20:5411014 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
bnc55ff9da2015-08-19 18:42:3511015 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311016 session_deps_.next_protos = SpdyNextProtos();
[email protected]2ff8b312010-04-26 22:20:5411017
11018 HttpRequestInfo request;
11019 request.method = "GET";
bncce36dca22015-04-21 22:11:2311020 request.url = GURL("http://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5411021 request.load_flags = 0;
11022
[email protected]8a0fc822013-06-27 20:52:4311023 std::string alternate_protocol_http_header =
11024 GetAlternateProtocolHttpHeader();
11025
[email protected]2ff8b312010-04-26 22:20:5411026 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211027 MockRead("HTTP/1.1 200 OK\r\n"),
11028 MockRead(alternate_protocol_http_header.c_str()),
11029 MockRead("\r\n"),
11030 MockRead("hello world"),
11031 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5411032 };
11033
11034 StaticSocketDataProvider first_transaction(
11035 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0711036 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2ff8b312010-04-26 22:20:5411037
[email protected]8ddf8322012-02-23 18:08:0611038 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811039 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2311040 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11041 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0711042 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2ff8b312010-04-26 22:20:5411043
[email protected]cdf8f7e72013-05-23 10:56:4611044 scoped_ptr<SpdyFrame> req(
11045 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1311046 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]2ff8b312010-04-26 22:20:5411047
[email protected]23e482282013-06-14 16:08:0211048 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11049 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5411050 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1311051 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5411052 };
11053
rch8e6c6c42015-05-01 14:05:1311054 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11055 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711056 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5411057
[email protected]83039bb2011-12-09 18:43:5511058 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5411059
mmenkee65e7af2015-10-13 17:16:4211060 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5411061
[email protected]262eec82013-03-19 21:01:3611062 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011063 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5411064
[email protected]49639fa2011-12-20 23:22:4111065 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5411066 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4111067 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:5411068
11069 const HttpResponseInfo* response = trans->GetResponseInfo();
11070 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011071 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5411072 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11073
11074 std::string response_data;
11075 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11076 EXPECT_EQ("hello world", response_data);
11077
11078 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2311079 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4011080 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5311081 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2711082 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:4211083 CreateSecureSpdySession(session.get(), key, BoundNetLog());
[email protected]02b0c342010-09-25 21:09:3811084
[email protected]90499482013-06-01 00:39:5011085 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5411086
[email protected]49639fa2011-12-20 23:22:4111087 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5411088 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4111089 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:5411090
11091 response = trans->GetResponseInfo();
11092 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011093 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0211094 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5311095 EXPECT_TRUE(response->was_fetched_via_spdy);
11096 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5411097
11098 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11099 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4211100}
11101
[email protected]044de0642010-06-17 10:42:1511102// GenerateAuthToken is a mighty big test.
11103// It tests all permutation of GenerateAuthToken behavior:
11104// - Synchronous and Asynchronous completion.
11105// - OK or error on completion.
11106// - Direct connection, non-authenticating proxy, and authenticating proxy.
11107// - HTTP or HTTPS backend (to include proxy tunneling).
11108// - Non-authenticating and authenticating backend.
11109//
[email protected]fe3b7dc2012-02-03 19:52:0911110// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1511111// problems generating an auth token for an authenticating proxy, we don't
11112// need to test all permutations of the backend server).
11113//
11114// The test proceeds by going over each of the configuration cases, and
11115// potentially running up to three rounds in each of the tests. The TestConfig
11116// specifies both the configuration for the test as well as the expectations
11117// for the results.
[email protected]23e482282013-06-14 16:08:0211118TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5011119 static const char kServer[] = "http://www.example.com";
11120 static const char kSecureServer[] = "https://www.example.com";
11121 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1511122 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
11123
11124 enum AuthTiming {
11125 AUTH_NONE,
11126 AUTH_SYNC,
11127 AUTH_ASYNC,
11128 };
11129
11130 const MockWrite kGet(
11131 "GET / HTTP/1.1\r\n"
11132 "Host: www.example.com\r\n"
11133 "Connection: keep-alive\r\n\r\n");
11134 const MockWrite kGetProxy(
11135 "GET http://www.example.com/ HTTP/1.1\r\n"
11136 "Host: www.example.com\r\n"
11137 "Proxy-Connection: keep-alive\r\n\r\n");
11138 const MockWrite kGetAuth(
11139 "GET / HTTP/1.1\r\n"
11140 "Host: www.example.com\r\n"
11141 "Connection: keep-alive\r\n"
11142 "Authorization: auth_token\r\n\r\n");
11143 const MockWrite kGetProxyAuth(
11144 "GET http://www.example.com/ HTTP/1.1\r\n"
11145 "Host: www.example.com\r\n"
11146 "Proxy-Connection: keep-alive\r\n"
11147 "Proxy-Authorization: auth_token\r\n\r\n");
11148 const MockWrite kGetAuthThroughProxy(
11149 "GET http://www.example.com/ HTTP/1.1\r\n"
11150 "Host: www.example.com\r\n"
11151 "Proxy-Connection: keep-alive\r\n"
11152 "Authorization: auth_token\r\n\r\n");
11153 const MockWrite kGetAuthWithProxyAuth(
11154 "GET http://www.example.com/ HTTP/1.1\r\n"
11155 "Host: www.example.com\r\n"
11156 "Proxy-Connection: keep-alive\r\n"
11157 "Proxy-Authorization: auth_token\r\n"
11158 "Authorization: auth_token\r\n\r\n");
11159 const MockWrite kConnect(
11160 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711161 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1511162 "Proxy-Connection: keep-alive\r\n\r\n");
11163 const MockWrite kConnectProxyAuth(
11164 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711165 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1511166 "Proxy-Connection: keep-alive\r\n"
11167 "Proxy-Authorization: auth_token\r\n\r\n");
11168
11169 const MockRead kSuccess(
11170 "HTTP/1.1 200 OK\r\n"
11171 "Content-Type: text/html; charset=iso-8859-1\r\n"
11172 "Content-Length: 3\r\n\r\n"
11173 "Yes");
11174 const MockRead kFailure(
11175 "Should not be called.");
11176 const MockRead kServerChallenge(
11177 "HTTP/1.1 401 Unauthorized\r\n"
11178 "WWW-Authenticate: Mock realm=server\r\n"
11179 "Content-Type: text/html; charset=iso-8859-1\r\n"
11180 "Content-Length: 14\r\n\r\n"
11181 "Unauthorized\r\n");
11182 const MockRead kProxyChallenge(
11183 "HTTP/1.1 407 Unauthorized\r\n"
11184 "Proxy-Authenticate: Mock realm=proxy\r\n"
11185 "Proxy-Connection: close\r\n"
11186 "Content-Type: text/html; charset=iso-8859-1\r\n"
11187 "Content-Length: 14\r\n\r\n"
11188 "Unauthorized\r\n");
11189 const MockRead kProxyConnected(
11190 "HTTP/1.1 200 Connection Established\r\n\r\n");
11191
11192 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
11193 // no constructors, but the C++ compiler on Windows warns about
11194 // unspecified data in compound literals. So, moved to using constructors,
11195 // and TestRound's created with the default constructor should not be used.
11196 struct TestRound {
11197 TestRound()
11198 : expected_rv(ERR_UNEXPECTED),
11199 extra_write(NULL),
11200 extra_read(NULL) {
11201 }
11202 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
11203 int expected_rv_arg)
11204 : write(write_arg),
11205 read(read_arg),
11206 expected_rv(expected_rv_arg),
11207 extra_write(NULL),
11208 extra_read(NULL) {
11209 }
11210 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
11211 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0111212 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1511213 : write(write_arg),
11214 read(read_arg),
11215 expected_rv(expected_rv_arg),
11216 extra_write(extra_write_arg),
11217 extra_read(extra_read_arg) {
11218 }
11219 MockWrite write;
11220 MockRead read;
11221 int expected_rv;
11222 const MockWrite* extra_write;
11223 const MockRead* extra_read;
11224 };
11225
11226 static const int kNoSSL = 500;
11227
11228 struct TestConfig {
thestig9d3bb0c2015-01-24 00:49:5111229 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1511230 AuthTiming proxy_auth_timing;
11231 int proxy_auth_rv;
thestig9d3bb0c2015-01-24 00:49:5111232 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1511233 AuthTiming server_auth_timing;
11234 int server_auth_rv;
11235 int num_auth_rounds;
11236 int first_ssl_round;
11237 TestRound rounds[3];
11238 } test_configs[] = {
11239 // Non-authenticating HTTP server with a direct connection.
11240 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
11241 { TestRound(kGet, kSuccess, OK)}},
11242 // Authenticating HTTP server with a direct connection.
11243 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
11244 { TestRound(kGet, kServerChallenge, OK),
11245 TestRound(kGetAuth, kSuccess, OK)}},
11246 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
11247 { TestRound(kGet, kServerChallenge, OK),
11248 TestRound(kGetAuth, kFailure, kAuthErr)}},
11249 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
11250 { TestRound(kGet, kServerChallenge, OK),
11251 TestRound(kGetAuth, kSuccess, OK)}},
11252 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
11253 { TestRound(kGet, kServerChallenge, OK),
11254 TestRound(kGetAuth, kFailure, kAuthErr)}},
11255 // Non-authenticating HTTP server through a non-authenticating proxy.
11256 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
11257 { TestRound(kGetProxy, kSuccess, OK)}},
11258 // Authenticating HTTP server through a non-authenticating proxy.
11259 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
11260 { TestRound(kGetProxy, kServerChallenge, OK),
11261 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
11262 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
11263 { TestRound(kGetProxy, kServerChallenge, OK),
11264 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
11265 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
11266 { TestRound(kGetProxy, kServerChallenge, OK),
11267 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
11268 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
11269 { TestRound(kGetProxy, kServerChallenge, OK),
11270 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
11271 // Non-authenticating HTTP server through an authenticating proxy.
11272 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
11273 { TestRound(kGetProxy, kProxyChallenge, OK),
11274 TestRound(kGetProxyAuth, kSuccess, OK)}},
11275 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
11276 { TestRound(kGetProxy, kProxyChallenge, OK),
11277 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
11278 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
11279 { TestRound(kGetProxy, kProxyChallenge, OK),
11280 TestRound(kGetProxyAuth, kSuccess, OK)}},
11281 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
11282 { TestRound(kGetProxy, kProxyChallenge, OK),
11283 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
11284 // Authenticating HTTP server through an authenticating proxy.
11285 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
11286 { TestRound(kGetProxy, kProxyChallenge, OK),
11287 TestRound(kGetProxyAuth, kServerChallenge, OK),
11288 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11289 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
11290 { TestRound(kGetProxy, kProxyChallenge, OK),
11291 TestRound(kGetProxyAuth, kServerChallenge, OK),
11292 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11293 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
11294 { TestRound(kGetProxy, kProxyChallenge, OK),
11295 TestRound(kGetProxyAuth, kServerChallenge, OK),
11296 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11297 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
11298 { TestRound(kGetProxy, kProxyChallenge, OK),
11299 TestRound(kGetProxyAuth, kServerChallenge, OK),
11300 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11301 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
11302 { TestRound(kGetProxy, kProxyChallenge, OK),
11303 TestRound(kGetProxyAuth, kServerChallenge, OK),
11304 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11305 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
11306 { TestRound(kGetProxy, kProxyChallenge, OK),
11307 TestRound(kGetProxyAuth, kServerChallenge, OK),
11308 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11309 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
11310 { TestRound(kGetProxy, kProxyChallenge, OK),
11311 TestRound(kGetProxyAuth, kServerChallenge, OK),
11312 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11313 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
11314 { TestRound(kGetProxy, kProxyChallenge, OK),
11315 TestRound(kGetProxyAuth, kServerChallenge, OK),
11316 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11317 // Non-authenticating HTTPS server with a direct connection.
11318 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
11319 { TestRound(kGet, kSuccess, OK)}},
11320 // Authenticating HTTPS server with a direct connection.
11321 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
11322 { TestRound(kGet, kServerChallenge, OK),
11323 TestRound(kGetAuth, kSuccess, OK)}},
11324 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
11325 { TestRound(kGet, kServerChallenge, OK),
11326 TestRound(kGetAuth, kFailure, kAuthErr)}},
11327 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
11328 { TestRound(kGet, kServerChallenge, OK),
11329 TestRound(kGetAuth, kSuccess, OK)}},
11330 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
11331 { TestRound(kGet, kServerChallenge, OK),
11332 TestRound(kGetAuth, kFailure, kAuthErr)}},
11333 // Non-authenticating HTTPS server with a non-authenticating proxy.
11334 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
11335 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
11336 // Authenticating HTTPS server through a non-authenticating proxy.
11337 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
11338 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11339 TestRound(kGetAuth, kSuccess, OK)}},
11340 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
11341 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11342 TestRound(kGetAuth, kFailure, kAuthErr)}},
11343 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
11344 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11345 TestRound(kGetAuth, kSuccess, OK)}},
11346 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
11347 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11348 TestRound(kGetAuth, kFailure, kAuthErr)}},
11349 // Non-Authenticating HTTPS server through an authenticating proxy.
11350 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
11351 { TestRound(kConnect, kProxyChallenge, OK),
11352 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
11353 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
11354 { TestRound(kConnect, kProxyChallenge, OK),
11355 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
11356 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
11357 { TestRound(kConnect, kProxyChallenge, OK),
11358 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
11359 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
11360 { TestRound(kConnect, kProxyChallenge, OK),
11361 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
11362 // Authenticating HTTPS server through an authenticating proxy.
11363 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11364 { TestRound(kConnect, kProxyChallenge, OK),
11365 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11366 &kGet, &kServerChallenge),
11367 TestRound(kGetAuth, kSuccess, OK)}},
11368 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11369 { TestRound(kConnect, kProxyChallenge, OK),
11370 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11371 &kGet, &kServerChallenge),
11372 TestRound(kGetAuth, kFailure, kAuthErr)}},
11373 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11374 { TestRound(kConnect, kProxyChallenge, OK),
11375 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11376 &kGet, &kServerChallenge),
11377 TestRound(kGetAuth, kSuccess, OK)}},
11378 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11379 { TestRound(kConnect, kProxyChallenge, OK),
11380 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11381 &kGet, &kServerChallenge),
11382 TestRound(kGetAuth, kFailure, kAuthErr)}},
11383 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11384 { TestRound(kConnect, kProxyChallenge, OK),
11385 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11386 &kGet, &kServerChallenge),
11387 TestRound(kGetAuth, kSuccess, OK)}},
11388 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11389 { TestRound(kConnect, kProxyChallenge, OK),
11390 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11391 &kGet, &kServerChallenge),
11392 TestRound(kGetAuth, kFailure, kAuthErr)}},
11393 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11394 { TestRound(kConnect, kProxyChallenge, OK),
11395 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11396 &kGet, &kServerChallenge),
11397 TestRound(kGetAuth, kSuccess, OK)}},
11398 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11399 { TestRound(kConnect, kProxyChallenge, OK),
11400 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11401 &kGet, &kServerChallenge),
11402 TestRound(kGetAuth, kFailure, kAuthErr)}},
11403 };
11404
viettrungluue4a8b882014-10-16 06:17:3811405 for (size_t i = 0; i < arraysize(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:0811406 HttpAuthHandlerMock::Factory* auth_factory(
11407 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711408 session_deps_.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:1511409 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:2611410
11411 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1511412 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:0811413 for (int n = 0; n < 2; n++) {
11414 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11415 std::string auth_challenge = "Mock realm=proxy";
11416 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2411417 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11418 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0811419 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
11420 origin, BoundNetLog());
11421 auth_handler->SetGenerateExpectation(
11422 test_config.proxy_auth_timing == AUTH_ASYNC,
11423 test_config.proxy_auth_rv);
11424 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
11425 }
[email protected]044de0642010-06-17 10:42:1511426 }
11427 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0011428 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1511429 std::string auth_challenge = "Mock realm=server";
11430 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2411431 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11432 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1511433 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
11434 origin, BoundNetLog());
11435 auth_handler->SetGenerateExpectation(
11436 test_config.server_auth_timing == AUTH_ASYNC,
11437 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:0811438 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1511439 }
11440 if (test_config.proxy_url) {
rdsmith82957ad2015-09-16 19:42:0311441 session_deps_.proxy_service =
11442 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:1511443 } else {
rdsmith82957ad2015-09-16 19:42:0311444 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1511445 }
11446
11447 HttpRequestInfo request;
11448 request.method = "GET";
11449 request.url = GURL(test_config.server_url);
11450 request.load_flags = 0;
11451
mmenkee65e7af2015-10-13 17:16:4211452 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1511453
rchcb68dc62015-05-21 04:45:3611454 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
11455
11456 std::vector<std::vector<MockRead>> mock_reads(1);
11457 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1511458 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11459 const TestRound& read_write_round = test_config.rounds[round];
11460
11461 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3611462 mock_reads.back().push_back(read_write_round.read);
11463 mock_writes.back().push_back(read_write_round.write);
11464
11465 // kProxyChallenge uses Proxy-Connection: close which means that the
11466 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5411467 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3611468 mock_reads.push_back(std::vector<MockRead>());
11469 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1511470 }
11471
rchcb68dc62015-05-21 04:45:3611472 if (read_write_round.extra_read) {
11473 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1511474 }
rchcb68dc62015-05-21 04:45:3611475 if (read_write_round.extra_write) {
11476 mock_writes.back().push_back(*read_write_round.extra_write);
11477 }
[email protected]044de0642010-06-17 10:42:1511478
11479 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1511480 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0711481 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1511482 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3611483 }
[email protected]044de0642010-06-17 10:42:1511484
olli.raula525048c2015-12-10 07:38:3211485 std::vector<scoped_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3611486 for (size_t i = 0; i < mock_reads.size(); ++i) {
olli.raula525048c2015-12-10 07:38:3211487 data_providers.push_back(make_scoped_ptr(new StaticSocketDataProvider(
davidben5f8b6bc2015-11-25 03:19:5411488 mock_reads[i].data(), mock_reads[i].size(), mock_writes[i].data(),
olli.raula525048c2015-12-10 07:38:3211489 mock_writes[i].size())));
rchcb68dc62015-05-21 04:45:3611490 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3211491 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3611492 }
11493
mmenkecc2298e2015-12-07 18:20:1811494 // Transaction must be created after DataProviders, so it's destroyed before
11495 // they are as well.
11496 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11497
rchcb68dc62015-05-21 04:45:3611498 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11499 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1511500 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4111501 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1511502 int rv;
11503 if (round == 0) {
[email protected]49639fa2011-12-20 23:22:4111504 rv = trans.Start(&request, callback.callback(), BoundNetLog());
[email protected]044de0642010-06-17 10:42:1511505 } else {
[email protected]49639fa2011-12-20 23:22:4111506 rv = trans.RestartWithAuth(
11507 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1511508 }
11509 if (rv == ERR_IO_PENDING)
11510 rv = callback.WaitForResult();
11511
11512 // Compare results with expected data.
11513 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:5011514 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5511515 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1511516 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
11517 continue;
11518 }
11519 if (round + 1 < test_config.num_auth_rounds) {
11520 EXPECT_FALSE(response->auth_challenge.get() == NULL);
11521 } else {
11522 EXPECT_TRUE(response->auth_challenge.get() == NULL);
11523 }
11524 }
[email protected]e5ae96a2010-04-14 20:12:4511525 }
11526}
11527
[email protected]23e482282013-06-14 16:08:0211528TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1411529 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1411530 HttpAuthHandlerMock::Factory* auth_factory(
11531 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711532 session_deps_.http_auth_handler_factory.reset(auth_factory);
rdsmith82957ad2015-09-16 19:42:0311533 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0711534 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
11535 session_deps_.host_resolver->set_synchronous_mode(true);
[email protected]c871bce92010-07-15 21:51:1411536
11537 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11538 auth_handler->set_connection_based(true);
11539 std::string auth_challenge = "Mock realm=server";
11540 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2411541 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11542 auth_challenge.end());
[email protected]c871bce92010-07-15 21:51:1411543 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
11544 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:0811545 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1411546
[email protected]c871bce92010-07-15 21:51:1411547 int rv = OK;
11548 const HttpResponseInfo* response = NULL;
11549 HttpRequestInfo request;
11550 request.method = "GET";
11551 request.url = origin;
11552 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:2711553
mmenkee65e7af2015-10-13 17:16:4211554 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1011555
11556 // Use a TCP Socket Pool with only one connection per group. This is used
11557 // to validate that the TCP socket is not released to the pool between
11558 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4211559 HttpNetworkSessionPeer session_peer(session.get());
[email protected]ab739042011-04-07 15:22:2811560 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:1011561 50, // Max sockets for pool
11562 1, // Max sockets per group
[email protected]bb88e1d32013-05-03 23:11:0711563 session_deps_.host_resolver.get(),
11564 session_deps_.socket_factory.get(),
11565 session_deps_.net_log);
[email protected]831e4a32013-11-14 02:14:4411566 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
11567 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:0211568 mock_pool_manager->SetTransportSocketPool(transport_pool);
dchengc7eeda422015-12-26 03:56:4811569 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1011570
[email protected]262eec82013-03-19 21:01:3611571 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011572 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111573 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1411574
11575 const MockWrite kGet(
11576 "GET / HTTP/1.1\r\n"
11577 "Host: www.example.com\r\n"
11578 "Connection: keep-alive\r\n\r\n");
11579 const MockWrite kGetAuth(
11580 "GET / HTTP/1.1\r\n"
11581 "Host: www.example.com\r\n"
11582 "Connection: keep-alive\r\n"
11583 "Authorization: auth_token\r\n\r\n");
11584
11585 const MockRead kServerChallenge(
11586 "HTTP/1.1 401 Unauthorized\r\n"
11587 "WWW-Authenticate: Mock realm=server\r\n"
11588 "Content-Type: text/html; charset=iso-8859-1\r\n"
11589 "Content-Length: 14\r\n\r\n"
11590 "Unauthorized\r\n");
11591 const MockRead kSuccess(
11592 "HTTP/1.1 200 OK\r\n"
11593 "Content-Type: text/html; charset=iso-8859-1\r\n"
11594 "Content-Length: 3\r\n\r\n"
11595 "Yes");
11596
11597 MockWrite writes[] = {
11598 // First round
11599 kGet,
11600 // Second round
11601 kGetAuth,
11602 // Third round
11603 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3011604 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1011605 kGetAuth,
11606 // Competing request
11607 kGet,
[email protected]c871bce92010-07-15 21:51:1411608 };
11609 MockRead reads[] = {
11610 // First round
11611 kServerChallenge,
11612 // Second round
11613 kServerChallenge,
11614 // Third round
[email protected]eca50e122010-09-11 14:03:3011615 kServerChallenge,
11616 // Fourth round
[email protected]c871bce92010-07-15 21:51:1411617 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1011618 // Competing response
11619 kSuccess,
[email protected]c871bce92010-07-15 21:51:1411620 };
11621 StaticSocketDataProvider data_provider(reads, arraysize(reads),
11622 writes, arraysize(writes));
[email protected]bb88e1d32013-05-03 23:11:0711623 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1411624
thestig9d3bb0c2015-01-24 00:49:5111625 const char kSocketGroup[] = "www.example.com:80";
[email protected]7ef4cbbb2011-02-06 11:19:1011626
11627 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1411628 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111629 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]c871bce92010-07-15 21:51:1411630 if (rv == ERR_IO_PENDING)
11631 rv = callback.WaitForResult();
11632 EXPECT_EQ(OK, rv);
11633 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011634 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411635 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811636 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411637
[email protected]7ef4cbbb2011-02-06 11:19:1011638 // In between rounds, another request comes in for the same domain.
11639 // It should not be able to grab the TCP socket that trans has already
11640 // claimed.
11641 scoped_ptr<HttpTransaction> trans_compete(
[email protected]90499482013-06-01 00:39:5011642 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111643 TestCompletionCallback callback_compete;
11644 rv = trans_compete->Start(
11645 &request, callback_compete.callback(), BoundNetLog());
[email protected]7ef4cbbb2011-02-06 11:19:1011646 EXPECT_EQ(ERR_IO_PENDING, rv);
11647 // callback_compete.WaitForResult at this point would stall forever,
11648 // since the HttpNetworkTransaction does not release the request back to
11649 // the pool until after authentication completes.
11650
11651 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1411652 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111653 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411654 if (rv == ERR_IO_PENDING)
11655 rv = callback.WaitForResult();
11656 EXPECT_EQ(OK, rv);
11657 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011658 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411659 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811660 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411661
[email protected]7ef4cbbb2011-02-06 11:19:1011662 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1411663 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111664 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411665 if (rv == ERR_IO_PENDING)
11666 rv = callback.WaitForResult();
11667 EXPECT_EQ(OK, rv);
11668 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011669 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411670 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811671 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:3011672
[email protected]7ef4cbbb2011-02-06 11:19:1011673 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3011674 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111675 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3011676 if (rv == ERR_IO_PENDING)
11677 rv = callback.WaitForResult();
11678 EXPECT_EQ(OK, rv);
11679 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011680 ASSERT_TRUE(response != NULL);
[email protected]eca50e122010-09-11 14:03:3011681 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811682 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011683
11684 // Read the body since the fourth round was successful. This will also
11685 // release the socket back to the pool.
11686 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
[email protected]90499482013-06-01 00:39:5011687 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011688 if (rv == ERR_IO_PENDING)
11689 rv = callback.WaitForResult();
11690 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011691 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011692 EXPECT_EQ(0, rv);
11693 // There are still 0 idle sockets, since the trans_compete transaction
11694 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:2811695 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011696
11697 // The competing request can now finish. Wait for the headers and then
11698 // read the body.
11699 rv = callback_compete.WaitForResult();
11700 EXPECT_EQ(OK, rv);
[email protected]90499482013-06-01 00:39:5011701 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011702 if (rv == ERR_IO_PENDING)
11703 rv = callback.WaitForResult();
11704 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011705 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011706 EXPECT_EQ(0, rv);
11707
11708 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:2811709 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411710}
11711
[email protected]65041fa2010-05-21 06:56:5311712// This tests the case that a request is issued via http instead of spdy after
11713// npn is negotiated.
[email protected]23e482282013-06-14 16:08:0211714TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
bnc55ff9da2015-08-19 18:42:3511715 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311716 NextProtoVector next_protos;
[email protected]0ce3af82013-07-22 16:17:1611717 next_protos.push_back(kProtoHTTP11);
[email protected]d7599122014-05-24 03:37:2311718 session_deps_.next_protos = next_protos;
11719
[email protected]65041fa2010-05-21 06:56:5311720 HttpRequestInfo request;
11721 request.method = "GET";
bncce36dca22015-04-21 22:11:2311722 request.url = GURL("https://www.example.org/");
[email protected]65041fa2010-05-21 06:56:5311723 request.load_flags = 0;
11724
11725 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311726 MockWrite(
11727 "GET / HTTP/1.1\r\n"
11728 "Host: www.example.org\r\n"
11729 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5311730 };
11731
[email protected]8a0fc822013-06-27 20:52:4311732 std::string alternate_protocol_http_header =
11733 GetAlternateProtocolHttpHeader();
11734
[email protected]65041fa2010-05-21 06:56:5311735 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211736 MockRead("HTTP/1.1 200 OK\r\n"),
11737 MockRead(alternate_protocol_http_header.c_str()),
11738 MockRead("\r\n"),
11739 MockRead("hello world"),
11740 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5311741 };
11742
[email protected]8ddf8322012-02-23 18:08:0611743 SSLSocketDataProvider ssl(ASYNC, OK);
davidben6974bf72015-04-27 17:52:4811744 ssl.SetNextProto(kProtoHTTP11);
[email protected]65041fa2010-05-21 06:56:5311745
[email protected]bb88e1d32013-05-03 23:11:0711746 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5311747
11748 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11749 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0711750 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5311751
[email protected]49639fa2011-12-20 23:22:4111752 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5311753
mmenkee65e7af2015-10-13 17:16:4211754 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3611755 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011756 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]65041fa2010-05-21 06:56:5311757
[email protected]49639fa2011-12-20 23:22:4111758 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]65041fa2010-05-21 06:56:5311759
11760 EXPECT_EQ(ERR_IO_PENDING, rv);
11761 EXPECT_EQ(OK, callback.WaitForResult());
11762
11763 const HttpResponseInfo* response = trans->GetResponseInfo();
11764 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011765 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]65041fa2010-05-21 06:56:5311766 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11767
11768 std::string response_data;
11769 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11770 EXPECT_EQ("hello world", response_data);
11771
11772 EXPECT_FALSE(response->was_fetched_via_spdy);
11773 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]65041fa2010-05-21 06:56:5311774}
[email protected]26ef6582010-06-24 02:30:4711775
bnc55ff9da2015-08-19 18:42:3511776// Simulate the SSL handshake completing with an NPN negotiation followed by an
11777// immediate server closing of the socket.
11778// Regression test for https://crbug.com/46369.
[email protected]23e482282013-06-14 16:08:0211779TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
bnc55ff9da2015-08-19 18:42:3511780 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311781 session_deps_.next_protos = SpdyNextProtos();
[email protected]26ef6582010-06-24 02:30:4711782
11783 HttpRequestInfo request;
11784 request.method = "GET";
bncce36dca22015-04-21 22:11:2311785 request.url = GURL("https://www.example.org/");
[email protected]26ef6582010-06-24 02:30:4711786 request.load_flags = 0;
11787
[email protected]8ddf8322012-02-23 18:08:0611788 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811789 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0711790 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4711791
[email protected]cdf8f7e72013-05-23 10:56:4611792 scoped_ptr<SpdyFrame> req(
11793 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1311794 MockWrite spdy_writes[] = {CreateMockWrite(*req, 1)};
[email protected]26ef6582010-06-24 02:30:4711795
11796 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0611797 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4711798 };
11799
rch8e6c6c42015-05-01 14:05:1311800 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11801 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711802 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4711803
[email protected]49639fa2011-12-20 23:22:4111804 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4711805
mmenkee65e7af2015-10-13 17:16:4211806 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3611807 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011808 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]26ef6582010-06-24 02:30:4711809
[email protected]49639fa2011-12-20 23:22:4111810 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]26ef6582010-06-24 02:30:4711811 EXPECT_EQ(ERR_IO_PENDING, rv);
11812 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
[email protected]26ef6582010-06-24 02:30:4711813}
[email protected]65d34382010-07-01 18:12:2611814
[email protected]795cbf82013-07-22 09:37:2711815// A subclass of HttpAuthHandlerMock that records the request URL when
11816// it gets it. This is needed since the auth handler may get destroyed
11817// before we get a chance to query it.
11818class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
11819 public:
11820 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
11821
dchengb03027d2014-10-21 12:00:2011822 ~UrlRecordingHttpAuthHandlerMock() override {}
[email protected]795cbf82013-07-22 09:37:2711823
11824 protected:
dchengb03027d2014-10-21 12:00:2011825 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
11826 const HttpRequestInfo* request,
11827 const CompletionCallback& callback,
11828 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2711829 *url_ = request->url;
11830 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
11831 credentials, request, callback, auth_token);
11832 }
11833
11834 private:
11835 GURL* url_;
11836};
11837
bnc55ff9da2015-08-19 18:42:3511838// This test ensures that the URL passed into the proxy is upgraded to https
11839// when doing an Alternate Protocol upgrade.
[email protected]23e482282013-06-14 16:08:0211840TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
bnc55ff9da2015-08-19 18:42:3511841 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2311842 session_deps_.next_protos = SpdyNextProtos();
[email protected]f45c1ee2010-08-03 00:54:3011843
rdsmith82957ad2015-09-16 19:42:0311844 session_deps_.proxy_service =
11845 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5111846 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711847 session_deps_.net_log = &net_log;
[email protected]795cbf82013-07-22 09:37:2711848 GURL request_url;
11849 {
11850 HttpAuthHandlerMock::Factory* auth_factory =
11851 new HttpAuthHandlerMock::Factory();
11852 UrlRecordingHttpAuthHandlerMock* auth_handler =
11853 new UrlRecordingHttpAuthHandlerMock(&request_url);
11854 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
11855 auth_factory->set_do_init_from_challenge(true);
11856 session_deps_.http_auth_handler_factory.reset(auth_factory);
11857 }
[email protected]f45c1ee2010-08-03 00:54:3011858
11859 HttpRequestInfo request;
11860 request.method = "GET";
bncce36dca22015-04-21 22:11:2311861 request.url = GURL("http://www.example.org");
[email protected]f45c1ee2010-08-03 00:54:3011862 request.load_flags = 0;
11863
11864 // First round goes unauthenticated through the proxy.
11865 MockWrite data_writes_1[] = {
bncce36dca22015-04-21 22:11:2311866 MockWrite(
11867 "GET http://www.example.org/ HTTP/1.1\r\n"
11868 "Host: www.example.org\r\n"
11869 "Proxy-Connection: keep-alive\r\n"
11870 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011871 };
11872 MockRead data_reads_1[] = {
[email protected]8ddf8322012-02-23 18:08:0611873 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
bnc33b8cef42014-11-19 17:30:3811874 MockRead("HTTP/1.1 200 OK\r\n"),
11875 MockRead("Alternate-Protocol: 443:"),
11876 MockRead(GetAlternateProtocolFromParam()),
11877 MockRead("\r\n"),
11878 MockRead("Proxy-Connection: close\r\n"),
11879 MockRead("\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011880 };
11881 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
11882 data_writes_1, arraysize(data_writes_1));
11883
bncce36dca22015-04-21 22:11:2311884 // Second round tries to tunnel to www.example.org due to the
[email protected]f45c1ee2010-08-03 00:54:3011885 // Alternate-Protocol announcement in the first round. It fails due
11886 // to a proxy authentication challenge.
bncce36dca22015-04-21 22:11:2311887 // After the failure, a tunnel is established to www.example.org using
[email protected]394816e92010-08-03 07:38:5911888 // Proxy-Authorization headers. There is then a SPDY request round.
11889 //
[email protected]fe3b7dc2012-02-03 19:52:0911890 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
11891 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
11892 // does a Disconnect and Connect on the same socket, rather than trying
11893 // to obtain a new one.
11894 //
[email protected]394816e92010-08-03 07:38:5911895 // NOTE: Originally, the proxy response to the second CONNECT request
11896 // simply returned another 407 so the unit test could skip the SSL connection
11897 // establishment and SPDY framing issues. Alas, the
11898 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:3011899 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:5911900
[email protected]cdf8f7e72013-05-23 10:56:4611901 scoped_ptr<SpdyFrame> req(
11902 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]23e482282013-06-14 16:08:0211903 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11904 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]f45c1ee2010-08-03 00:54:3011905
[email protected]394816e92010-08-03 07:38:5911906 MockWrite data_writes_2[] = {
bncce36dca22015-04-21 22:11:2311907 // First connection attempt without Proxy-Authorization.
rch8e6c6c42015-05-01 14:05:1311908 MockWrite(ASYNC, 0,
11909 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711910 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1311911 "Proxy-Connection: keep-alive\r\n"
11912 "\r\n"),
[email protected]394816e92010-08-03 07:38:5911913
bncce36dca22015-04-21 22:11:2311914 // Second connection attempt with Proxy-Authorization.
rch8e6c6c42015-05-01 14:05:1311915 MockWrite(ASYNC, 2,
11916 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711917 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1311918 "Proxy-Connection: keep-alive\r\n"
11919 "Proxy-Authorization: auth_token\r\n"
11920 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011921
bncce36dca22015-04-21 22:11:2311922 // SPDY request
rch8e6c6c42015-05-01 14:05:1311923 CreateMockWrite(*req, 4),
[email protected]f45c1ee2010-08-03 00:54:3011924 };
[email protected]394816e92010-08-03 07:38:5911925 MockRead data_reads_2[] = {
rch8e6c6c42015-05-01 14:05:1311926 // First connection attempt fails
mmenkee71e15332015-10-07 16:39:5411927 MockRead(ASYNC, 1,
11928 "HTTP/1.1 407 Unauthorized\r\n"
11929 "Proxy-Authenticate: Mock\r\n"
11930 "Content-Length: 0\r\n"
11931 "Proxy-Connection: keep-alive\r\n"
11932 "\r\n"),
[email protected]394816e92010-08-03 07:38:5911933
rch8e6c6c42015-05-01 14:05:1311934 // Second connection attempt passes
mmenkee71e15332015-10-07 16:39:5411935 MockRead(ASYNC, 3, "HTTP/1.1 200 Connected\r\n\r\n"),
[email protected]394816e92010-08-03 07:38:5911936
rch8e6c6c42015-05-01 14:05:1311937 // SPDY response
mmenkee71e15332015-10-07 16:39:5411938 CreateMockRead(*resp.get(), 5), CreateMockRead(*data.get(), 6),
rch8e6c6c42015-05-01 14:05:1311939 MockRead(ASYNC, 0, 0, 7),
[email protected]394816e92010-08-03 07:38:5911940 };
rch8e6c6c42015-05-01 14:05:1311941 SequencedSocketData data_2(data_reads_2, arraysize(data_reads_2),
11942 data_writes_2, arraysize(data_writes_2));
[email protected]f45c1ee2010-08-03 00:54:3011943
[email protected]8ddf8322012-02-23 18:08:0611944 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811945 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2311946 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11947 ASSERT_TRUE(ssl.cert.get());
[email protected]f45c1ee2010-08-03 00:54:3011948
[email protected]d973e99a2012-02-17 21:02:3611949 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5511950 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
11951 NULL, 0, NULL, 0);
11952 hanging_non_alternate_protocol_socket.set_connect_data(
11953 never_finishing_connect);
11954
[email protected]bb88e1d32013-05-03 23:11:0711955 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
11956 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
11957 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11958 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5511959 &hanging_non_alternate_protocol_socket);
mmenkee65e7af2015-10-13 17:16:4211960 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f45c1ee2010-08-03 00:54:3011961
11962 // First round should work and provide the Alternate-Protocol state.
[email protected]49639fa2011-12-20 23:22:4111963 TestCompletionCallback callback_1;
[email protected]262eec82013-03-19 21:01:3611964 scoped_ptr<HttpTransaction> trans_1(
[email protected]90499482013-06-01 00:39:5011965 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111966 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:3011967 EXPECT_EQ(ERR_IO_PENDING, rv);
11968 EXPECT_EQ(OK, callback_1.WaitForResult());
11969
11970 // Second round should attempt a tunnel connect and get an auth challenge.
[email protected]49639fa2011-12-20 23:22:4111971 TestCompletionCallback callback_2;
[email protected]262eec82013-03-19 21:01:3611972 scoped_ptr<HttpTransaction> trans_2(
[email protected]90499482013-06-01 00:39:5011973 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111974 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:3011975 EXPECT_EQ(ERR_IO_PENDING, rv);
11976 EXPECT_EQ(OK, callback_2.WaitForResult());
11977 const HttpResponseInfo* response = trans_2->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011978 ASSERT_TRUE(response != NULL);
[email protected]f45c1ee2010-08-03 00:54:3011979 ASSERT_FALSE(response->auth_challenge.get() == NULL);
11980
11981 // Restart with auth. Tunnel should work and response received.
[email protected]49639fa2011-12-20 23:22:4111982 TestCompletionCallback callback_3;
11983 rv = trans_2->RestartWithAuth(
11984 AuthCredentials(kFoo, kBar), callback_3.callback());
[email protected]f45c1ee2010-08-03 00:54:3011985 EXPECT_EQ(ERR_IO_PENDING, rv);
11986 EXPECT_EQ(OK, callback_3.WaitForResult());
11987
11988 // After all that work, these two lines (or actually, just the scheme) are
11989 // what this test is all about. Make sure it happens correctly.
[email protected]f45c1ee2010-08-03 00:54:3011990 EXPECT_EQ("https", request_url.scheme());
bncce36dca22015-04-21 22:11:2311991 EXPECT_EQ("www.example.org", request_url.host());
[email protected]f45c1ee2010-08-03 00:54:3011992
[email protected]029c83b62013-01-24 05:28:2011993 LoadTimingInfo load_timing_info;
11994 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
11995 TestLoadTimingNotReusedWithPac(load_timing_info,
11996 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]8e6441ca2010-08-19 05:56:3811997}
11998
11999// Test that if we cancel the transaction as the connection is completing, that
12000// everything tears down correctly.
[email protected]23e482282013-06-14 16:08:0212001TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3812002 // Setup everything about the connection to complete synchronously, so that
12003 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
12004 // for is the callback from the HttpStreamRequest.
12005 // Then cancel the transaction.
12006 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3612007 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3812008 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0612009 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
12010 MockRead(SYNCHRONOUS, "hello world"),
12011 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3812012 };
12013
[email protected]8e6441ca2010-08-19 05:56:3812014 HttpRequestInfo request;
12015 request.method = "GET";
bncce36dca22015-04-21 22:11:2312016 request.url = GURL("http://www.example.org/");
[email protected]8e6441ca2010-08-19 05:56:3812017 request.load_flags = 0;
12018
[email protected]bb88e1d32013-05-03 23:11:0712019 session_deps_.host_resolver->set_synchronous_mode(true);
mmenkee65e7af2015-10-13 17:16:4212020 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:2712021 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4112022 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:2712023
[email protected]8e6441ca2010-08-19 05:56:3812024 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
12025 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712026 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3812027
[email protected]49639fa2011-12-20 23:22:4112028 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3812029
vishal.b62985ca92015-04-17 08:45:5112030 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4112031 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]8e6441ca2010-08-19 05:56:3812032 EXPECT_EQ(ERR_IO_PENDING, rv);
12033 trans.reset(); // Cancel the transaction here.
12034
[email protected]2da659e2013-05-23 20:51:3412035 base::MessageLoop::current()->RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3012036}
12037
[email protected]ecab6e052014-05-16 14:58:1212038// Test that if a transaction is cancelled after receiving the headers, the
12039// stream is drained properly and added back to the socket pool. The main
12040// purpose of this test is to make sure that an HttpStreamParser can be read
12041// from after the HttpNetworkTransaction and the objects it owns have been
12042// deleted.
12043// See http://crbug.com/368418
12044TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
12045 MockRead data_reads[] = {
12046 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
12047 MockRead(ASYNC, "Content-Length: 2\r\n"),
12048 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
12049 MockRead(ASYNC, "1"),
12050 // 2 async reads are necessary to trigger a ReadResponseBody call after the
12051 // HttpNetworkTransaction has been deleted.
12052 MockRead(ASYNC, "2"),
12053 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
12054 };
12055 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
12056 session_deps_.socket_factory->AddSocketDataProvider(&data);
12057
mmenkee65e7af2015-10-13 17:16:4212058 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1212059
12060 {
12061 HttpRequestInfo request;
12062 request.method = "GET";
bncce36dca22015-04-21 22:11:2312063 request.url = GURL("http://www.example.org/");
[email protected]ecab6e052014-05-16 14:58:1212064 request.load_flags = 0;
12065
dcheng48459ac22014-08-26 00:46:4112066 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1212067 TestCompletionCallback callback;
12068
12069 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
12070 EXPECT_EQ(ERR_IO_PENDING, rv);
12071 callback.WaitForResult();
12072
12073 const HttpResponseInfo* response = trans.GetResponseInfo();
12074 ASSERT_TRUE(response != NULL);
12075 EXPECT_TRUE(response->headers.get() != NULL);
12076 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12077
12078 // The transaction and HttpRequestInfo are deleted.
12079 }
12080
12081 // Let the HttpResponseBodyDrainer drain the socket.
12082 base::MessageLoop::current()->RunUntilIdle();
12083
12084 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4112085 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1212086}
12087
[email protected]76a505b2010-08-25 06:23:0012088// Test a basic GET request through a proxy.
[email protected]23e482282013-06-14 16:08:0212089TEST_P(HttpNetworkTransactionTest, ProxyGet) {
rdsmith82957ad2015-09-16 19:42:0312090 session_deps_.proxy_service =
12091 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112092 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712093 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4212094 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012095
[email protected]76a505b2010-08-25 06:23:0012096 HttpRequestInfo request;
12097 request.method = "GET";
bncce36dca22015-04-21 22:11:2312098 request.url = GURL("http://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012099
12100 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312101 MockWrite(
12102 "GET http://www.example.org/ HTTP/1.1\r\n"
12103 "Host: www.example.org\r\n"
12104 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012105 };
12106
12107 MockRead data_reads1[] = {
12108 MockRead("HTTP/1.1 200 OK\r\n"),
12109 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12110 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612111 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0012112 };
12113
12114 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12115 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712116 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0012117
[email protected]49639fa2011-12-20 23:22:4112118 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012119
[email protected]262eec82013-03-19 21:01:3612120 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012121 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]597a1ab2014-06-26 08:12:2712122 BeforeProxyHeadersSentHandler proxy_headers_handler;
12123 trans->SetBeforeProxyHeadersSentCallback(
12124 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
12125 base::Unretained(&proxy_headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5012126
[email protected]49639fa2011-12-20 23:22:4112127 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0012128 EXPECT_EQ(ERR_IO_PENDING, rv);
12129
12130 rv = callback1.WaitForResult();
12131 EXPECT_EQ(OK, rv);
12132
12133 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5012134 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:0012135
12136 EXPECT_TRUE(response->headers->IsKeepAlive());
12137 EXPECT_EQ(200, response->headers->response_code());
12138 EXPECT_EQ(100, response->headers->GetContentLength());
12139 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1512140 EXPECT_TRUE(
12141 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
[email protected]597a1ab2014-06-26 08:12:2712142 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
12143 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0012144 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2012145
12146 LoadTimingInfo load_timing_info;
12147 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12148 TestLoadTimingNotReusedWithPac(load_timing_info,
12149 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0012150}
12151
12152// Test a basic HTTPS GET request through a proxy.
[email protected]23e482282013-06-14 16:08:0212153TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
rdsmith82957ad2015-09-16 19:42:0312154 session_deps_.proxy_service =
12155 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112156 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712157 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4212158 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012159
[email protected]76a505b2010-08-25 06:23:0012160 HttpRequestInfo request;
12161 request.method = "GET";
bncce36dca22015-04-21 22:11:2312162 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012163
12164 // Since we have proxy, should try to establish tunnel.
12165 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1712166 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
12167 "Host: www.example.org:443\r\n"
12168 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012169
rsleevidb16bb02015-11-12 23:47:1712170 MockWrite("GET / HTTP/1.1\r\n"
12171 "Host: www.example.org\r\n"
12172 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012173 };
12174
12175 MockRead data_reads1[] = {
12176 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
12177
12178 MockRead("HTTP/1.1 200 OK\r\n"),
12179 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12180 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612181 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0012182 };
12183
12184 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12185 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712186 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0612187 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712188 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0012189
[email protected]49639fa2011-12-20 23:22:4112190 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012191
[email protected]262eec82013-03-19 21:01:3612192 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012193 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:5012194
[email protected]49639fa2011-12-20 23:22:4112195 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0012196 EXPECT_EQ(ERR_IO_PENDING, rv);
12197
12198 rv = callback1.WaitForResult();
12199 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:4612200 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4012201 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0012202 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012203 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0012204 NetLog::PHASE_NONE);
12205 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012206 entries, pos,
[email protected]76a505b2010-08-25 06:23:0012207 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12208 NetLog::PHASE_NONE);
12209
12210 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5012211 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:0012212
12213 EXPECT_TRUE(response->headers->IsKeepAlive());
12214 EXPECT_EQ(200, response->headers->response_code());
12215 EXPECT_EQ(100, response->headers->GetContentLength());
12216 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
12217 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1512218 EXPECT_TRUE(
12219 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
[email protected]029c83b62013-01-24 05:28:2012220
12221 LoadTimingInfo load_timing_info;
12222 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12223 TestLoadTimingNotReusedWithPac(load_timing_info,
12224 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0012225}
12226
rsleevidb16bb02015-11-12 23:47:1712227// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
12228// literal host.
12229TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
12230 session_deps_.proxy_service =
12231 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
12232 BoundTestNetLog log;
12233 session_deps_.net_log = log.bound().net_log();
12234 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12235
12236 HttpRequestInfo request;
12237 request.method = "GET";
12238 request.url = GURL("https://[::1]:443/");
12239
12240 // Since we have proxy, should try to establish tunnel.
12241 MockWrite data_writes1[] = {
12242 MockWrite("CONNECT [::1]:443 HTTP/1.1\r\n"
12243 "Host: [::1]:443\r\n"
12244 "Proxy-Connection: keep-alive\r\n\r\n"),
12245
12246 MockWrite("GET / HTTP/1.1\r\n"
12247 "Host: [::1]\r\n"
12248 "Connection: keep-alive\r\n\r\n"),
12249 };
12250
12251 MockRead data_reads1[] = {
12252 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
12253
12254 MockRead("HTTP/1.1 200 OK\r\n"),
12255 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12256 MockRead("Content-Length: 100\r\n\r\n"),
12257 MockRead(SYNCHRONOUS, OK),
12258 };
12259
12260 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12261 data_writes1, arraysize(data_writes1));
12262 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12263 SSLSocketDataProvider ssl(ASYNC, OK);
12264 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12265
12266 TestCompletionCallback callback1;
12267
12268 scoped_ptr<HttpTransaction> trans(
12269 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12270
12271 int rv = trans->Start(&request, callback1.callback(), log.bound());
12272 EXPECT_EQ(ERR_IO_PENDING, rv);
12273
12274 rv = callback1.WaitForResult();
12275 EXPECT_EQ(OK, rv);
12276 TestNetLogEntry::List entries;
12277 log.GetEntries(&entries);
12278 size_t pos = ExpectLogContainsSomewhere(
12279 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
12280 NetLog::PHASE_NONE);
12281 ExpectLogContainsSomewhere(
12282 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12283 NetLog::PHASE_NONE);
12284
12285 const HttpResponseInfo* response = trans->GetResponseInfo();
12286 ASSERT_TRUE(response != NULL);
12287
12288 EXPECT_TRUE(response->headers->IsKeepAlive());
12289 EXPECT_EQ(200, response->headers->response_code());
12290 EXPECT_EQ(100, response->headers->GetContentLength());
12291 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
12292 EXPECT_TRUE(response->was_fetched_via_proxy);
12293 EXPECT_TRUE(
12294 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
12295
12296 LoadTimingInfo load_timing_info;
12297 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12298 TestLoadTimingNotReusedWithPac(load_timing_info,
12299 CONNECT_TIMING_HAS_SSL_TIMES);
12300}
12301
[email protected]76a505b2010-08-25 06:23:0012302// Test a basic HTTPS GET request through a proxy, but the server hangs up
12303// while establishing the tunnel.
[email protected]23e482282013-06-14 16:08:0212304TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
rdsmith82957ad2015-09-16 19:42:0312305 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112306 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712307 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4212308 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012309
[email protected]76a505b2010-08-25 06:23:0012310 HttpRequestInfo request;
12311 request.method = "GET";
bncce36dca22015-04-21 22:11:2312312 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012313
12314 // Since we have proxy, should try to establish tunnel.
12315 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1712316 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
12317 "Host: www.example.org:443\r\n"
12318 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012319
rsleevidb16bb02015-11-12 23:47:1712320 MockWrite("GET / HTTP/1.1\r\n"
12321 "Host: www.example.org\r\n"
12322 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012323 };
12324
12325 MockRead data_reads1[] = {
[email protected]8ddf8322012-02-23 18:08:0612326 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]76a505b2010-08-25 06:23:0012327 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612328 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0012329 };
12330
12331 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12332 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712333 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0612334 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712335 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0012336
[email protected]49639fa2011-12-20 23:22:4112337 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012338
[email protected]262eec82013-03-19 21:01:3612339 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012340 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:5012341
[email protected]49639fa2011-12-20 23:22:4112342 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0012343 EXPECT_EQ(ERR_IO_PENDING, rv);
12344
12345 rv = callback1.WaitForResult();
12346 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
mmenke43758e62015-05-04 21:09:4612347 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4012348 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0012349 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012350 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0012351 NetLog::PHASE_NONE);
12352 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012353 entries, pos,
[email protected]76a505b2010-08-25 06:23:0012354 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12355 NetLog::PHASE_NONE);
12356}
12357
[email protected]749eefa82010-09-13 22:14:0312358// Test for crbug.com/55424.
[email protected]23e482282013-06-14 16:08:0212359TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
[email protected]cdf8f7e72013-05-23 10:56:4612360 scoped_ptr<SpdyFrame> req(
bncce36dca22015-04-21 22:11:2312361 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rch8e6c6c42015-05-01 14:05:1312362 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]749eefa82010-09-13 22:14:0312363
[email protected]23e482282013-06-14 16:08:0212364 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12365 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0312366 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312367 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0312368 };
12369
rch8e6c6c42015-05-01 14:05:1312370 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
12371 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712372 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0312373
[email protected]8ddf8322012-02-23 18:08:0612374 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812375 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712376 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0312377
mmenkee65e7af2015-10-13 17:16:4212378 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0312379
12380 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2312381 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4012382 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5312383 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2712384 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:4212385 CreateInsecureSpdySession(session.get(), key, BoundNetLog());
[email protected]749eefa82010-09-13 22:14:0312386
12387 HttpRequestInfo request;
12388 request.method = "GET";
bncce36dca22015-04-21 22:11:2312389 request.url = GURL("https://www.example.org/");
[email protected]749eefa82010-09-13 22:14:0312390 request.load_flags = 0;
12391
12392 // This is the important line that marks this as a preconnect.
12393 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
12394
[email protected]262eec82013-03-19 21:01:3612395 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012396 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]749eefa82010-09-13 22:14:0312397
[email protected]41d64e82013-07-03 22:44:2612398 TestCompletionCallback callback;
[email protected]49639fa2011-12-20 23:22:4112399 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]749eefa82010-09-13 22:14:0312400 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112401 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]749eefa82010-09-13 22:14:0312402}
12403
[email protected]73b8dd222010-11-11 19:55:2412404// Given a net error, cause that error to be returned from the first Write()
12405// call and verify that the HttpTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0212406void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0712407 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2912408 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712409 request_info.url = GURL("https://www.example.com/");
12410 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912411 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712412
[email protected]8ddf8322012-02-23 18:08:0612413 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2912414 MockWrite data_writes[] = {
12415 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2412416 };
ttuttle859dc7a2015-04-23 19:42:2912417 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0712418 session_deps_.socket_factory->AddSocketDataProvider(&data);
12419 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2412420
mmenkee65e7af2015-10-13 17:16:4212421 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612422 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012423 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]73b8dd222010-11-11 19:55:2412424
[email protected]49639fa2011-12-20 23:22:4112425 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912426 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12427 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2412428 rv = callback.WaitForResult();
12429 ASSERT_EQ(error, rv);
12430}
12431
[email protected]23e482282013-06-14 16:08:0212432TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2412433 // Just check a grab bag of cert errors.
12434 static const int kErrors[] = {
12435 ERR_CERT_COMMON_NAME_INVALID,
12436 ERR_CERT_AUTHORITY_INVALID,
12437 ERR_CERT_DATE_INVALID,
12438 };
12439 for (size_t i = 0; i < arraysize(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0612440 CheckErrorIsPassedBack(kErrors[i], ASYNC);
12441 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2412442 }
12443}
12444
[email protected]bd0b6772011-01-11 19:59:3012445// Ensure that a client certificate is removed from the SSL client auth
12446// cache when:
12447// 1) No proxy is involved.
12448// 2) TLS False Start is disabled.
12449// 3) The initial TLS handshake requests a client certificate.
12450// 4) The client supplies an invalid/unacceptable certificate.
[email protected]23e482282013-06-14 16:08:0212451TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2312452 ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912453 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712454 request_info.url = GURL("https://www.example.com/");
12455 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912456 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712457
[email protected]bd0b6772011-01-11 19:59:3012458 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112459 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012460
12461 // [ssl_]data1 contains the data for the first SSL handshake. When a
12462 // CertificateRequest is received for the first time, the handshake will
12463 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2912464 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012465 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712466 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912467 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712468 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012469
12470 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
12471 // False Start is not being used, the result of the SSL handshake will be
12472 // returned as part of the SSLClientSocket::Connect() call. This test
12473 // matches the result of a server sending a handshake_failure alert,
12474 // rather than a Finished message, because it requires a client
12475 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2912476 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012477 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712478 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912479 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712480 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012481
12482 // [ssl_]data3 contains the data for the third SSL handshake. When a
12483 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212484 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
12485 // connection was attempted with TLSv1.2. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3012486 // of the HttpNetworkTransaction. Because this test failure is due to
12487 // requiring a client certificate, this fallback handshake should also
12488 // fail.
ttuttle859dc7a2015-04-23 19:42:2912489 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012490 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712491 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912492 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712493 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012494
[email protected]80c75f682012-05-26 16:22:1712495 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
12496 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212497 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
12498 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1712499 // of the HttpNetworkTransaction. Because this test failure is due to
12500 // requiring a client certificate, this fallback handshake should also
12501 // fail.
ttuttle859dc7a2015-04-23 19:42:2912502 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1712503 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712504 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912505 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712506 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712507
mmenkee65e7af2015-10-13 17:16:4212508 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612509 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012510 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012511
[email protected]bd0b6772011-01-11 19:59:3012512 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4112513 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912514 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12515 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012516
12517 // Complete the SSL handshake, which should abort due to requiring a
12518 // client certificate.
12519 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912520 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]bd0b6772011-01-11 19:59:3012521
12522 // Indicate that no certificate should be supplied. From the perspective
12523 // of SSLClientCertCache, NULL is just as meaningful as a real
12524 // certificate, so this is the same as supply a
12525 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412526 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912527 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012528
12529 // Ensure the certificate was added to the client auth cache before
12530 // allowing the connection to continue restarting.
12531 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412532 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112533 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412534 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012535 ASSERT_EQ(NULL, client_cert.get());
12536
12537 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712538 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12539 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012540 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912541 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
[email protected]bd0b6772011-01-11 19:59:3012542
12543 // Ensure that the client certificate is removed from the cache on a
12544 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112545 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412546 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012547}
12548
12549// Ensure that a client certificate is removed from the SSL client auth
12550// cache when:
12551// 1) No proxy is involved.
12552// 2) TLS False Start is enabled.
12553// 3) The initial TLS handshake requests a client certificate.
12554// 4) The client supplies an invalid/unacceptable certificate.
[email protected]23e482282013-06-14 16:08:0212555TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2312556 ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912557 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712558 request_info.url = GURL("https://www.example.com/");
12559 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912560 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712561
[email protected]bd0b6772011-01-11 19:59:3012562 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112563 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012564
12565 // When TLS False Start is used, SSLClientSocket::Connect() calls will
12566 // return successfully after reading up to the peer's Certificate message.
12567 // This is to allow the caller to call SSLClientSocket::Write(), which can
12568 // enqueue application data to be sent in the same packet as the
12569 // ChangeCipherSpec and Finished messages.
12570 // The actual handshake will be finished when SSLClientSocket::Read() is
12571 // called, which expects to process the peer's ChangeCipherSpec and
12572 // Finished messages. If there was an error negotiating with the peer,
12573 // such as due to the peer requiring a client certificate when none was
12574 // supplied, the alert sent by the peer won't be processed until Read() is
12575 // called.
12576
12577 // Like the non-False Start case, when a client certificate is requested by
12578 // the peer, the handshake is aborted during the Connect() call.
12579 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2912580 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012581 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712582 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912583 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712584 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012585
12586 // When a client certificate is supplied, Connect() will not be aborted
12587 // when the peer requests the certificate. Instead, the handshake will
12588 // artificially succeed, allowing the caller to write the HTTP request to
12589 // the socket. The handshake messages are not processed until Read() is
12590 // called, which then detects that the handshake was aborted, due to the
12591 // peer sending a handshake_failure because it requires a client
12592 // certificate.
ttuttle859dc7a2015-04-23 19:42:2912593 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012594 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712595 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912596 MockRead data2_reads[] = {
12597 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3012598 };
ttuttle859dc7a2015-04-23 19:42:2912599 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712600 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012601
12602 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1712603 // the data for the SSL handshake once the TLSv1.1 connection falls back to
12604 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912605 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012606 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712607 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912608 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712609 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012610
[email protected]80c75f682012-05-26 16:22:1712611 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
12612 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912613 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1712614 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712615 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912616 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712617 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712618
[email protected]7799de12013-05-30 05:52:5112619 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2912620 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5112621 ssl_data5.cert_request_info = cert_request.get();
12622 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
ttuttle859dc7a2015-04-23 19:42:2912623 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]7799de12013-05-30 05:52:5112624 session_deps_.socket_factory->AddSocketDataProvider(&data5);
12625
mmenkee65e7af2015-10-13 17:16:4212626 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612627 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012628 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012629
[email protected]bd0b6772011-01-11 19:59:3012630 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4112631 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912632 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12633 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012634
12635 // Complete the SSL handshake, which should abort due to requiring a
12636 // client certificate.
12637 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912638 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]bd0b6772011-01-11 19:59:3012639
12640 // Indicate that no certificate should be supplied. From the perspective
12641 // of SSLClientCertCache, NULL is just as meaningful as a real
12642 // certificate, so this is the same as supply a
12643 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412644 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912645 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012646
12647 // Ensure the certificate was added to the client auth cache before
12648 // allowing the connection to continue restarting.
12649 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412650 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112651 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412652 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012653 ASSERT_EQ(NULL, client_cert.get());
12654
[email protected]bd0b6772011-01-11 19:59:3012655 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712656 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12657 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012658 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912659 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
[email protected]bd0b6772011-01-11 19:59:3012660
12661 // Ensure that the client certificate is removed from the cache on a
12662 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112663 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412664 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012665}
12666
[email protected]8c405132011-01-11 22:03:1812667// Ensure that a client certificate is removed from the SSL client auth
12668// cache when:
12669// 1) An HTTPS proxy is involved.
12670// 3) The HTTPS proxy requests a client certificate.
12671// 4) The client supplies an invalid/unacceptable certificate for the
12672// proxy.
12673// The test is repeated twice, first for connecting to an HTTPS endpoint,
12674// then for connecting to an HTTP endpoint.
[email protected]23e482282013-06-14 16:08:0212675TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
rdsmith82957ad2015-09-16 19:42:0312676 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:5112677 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712678 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1812679
12680 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112681 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1812682
12683 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
12684 // [ssl_]data[1-3]. Rather than represending the endpoint
12685 // (www.example.com:443), they represent failures with the HTTPS proxy
12686 // (proxy:70).
ttuttle859dc7a2015-04-23 19:42:2912687 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8c405132011-01-11 22:03:1812688 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712689 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912690 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712691 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1812692
ttuttle859dc7a2015-04-23 19:42:2912693 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812694 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712695 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912696 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712697 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8c405132011-01-11 22:03:1812698
[email protected]80c75f682012-05-26 16:22:1712699 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
12700#if 0
ttuttle859dc7a2015-04-23 19:42:2912701 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812702 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712703 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912704 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712705 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]80c75f682012-05-26 16:22:1712706#endif
[email protected]8c405132011-01-11 22:03:1812707
ttuttle859dc7a2015-04-23 19:42:2912708 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1812709 requests[0].url = GURL("https://www.example.com/");
12710 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912711 requests[0].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812712
12713 requests[1].url = GURL("http://www.example.com/");
12714 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912715 requests[1].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812716
12717 for (size_t i = 0; i < arraysize(requests); ++i) {
[email protected]bb88e1d32013-05-03 23:11:0712718 session_deps_.socket_factory->ResetNextMockIndexes();
mmenkee65e7af2015-10-13 17:16:4212719 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c405132011-01-11 22:03:1812720 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5012721 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c405132011-01-11 22:03:1812722
12723 // Begin the SSL handshake with the proxy.
[email protected]49639fa2011-12-20 23:22:4112724 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912725 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
12726 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]8c405132011-01-11 22:03:1812727
12728 // Complete the SSL handshake, which should abort due to requiring a
12729 // client certificate.
12730 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912731 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]8c405132011-01-11 22:03:1812732
12733 // Indicate that no certificate should be supplied. From the perspective
12734 // of SSLClientCertCache, NULL is just as meaningful as a real
12735 // certificate, so this is the same as supply a
12736 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412737 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912738 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]8c405132011-01-11 22:03:1812739
12740 // Ensure the certificate was added to the client auth cache before
12741 // allowing the connection to continue restarting.
12742 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412743 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112744 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412745 HostPortPair("proxy", 70), &client_cert, &client_private_key));
[email protected]8c405132011-01-11 22:03:1812746 ASSERT_EQ(NULL, client_cert.get());
12747 // Ensure the certificate was NOT cached for the endpoint. This only
12748 // applies to HTTPS requests, but is fine to check for HTTP requests.
[email protected]791879c2013-12-17 07:22:4112749 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412750 HostPortPair("www.example.com", 443), &client_cert,
12751 &client_private_key));
[email protected]8c405132011-01-11 22:03:1812752
12753 // Restart the handshake. This will consume ssl_data2, which fails, and
12754 // then consume ssl_data3, which should also fail. The result code is
12755 // checked against what ssl_data3 should return.
12756 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912757 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]8c405132011-01-11 22:03:1812758
12759 // Now that the new handshake has failed, ensure that the client
12760 // certificate was removed from the client auth cache.
[email protected]791879c2013-12-17 07:22:4112761 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412762 HostPortPair("proxy", 70), &client_cert, &client_private_key));
[email protected]791879c2013-12-17 07:22:4112763 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412764 HostPortPair("www.example.com", 443), &client_cert,
12765 &client_private_key));
[email protected]8c405132011-01-11 22:03:1812766 }
12767}
12768
mmenke5c642132015-06-02 16:05:1312769TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
bnc55ff9da2015-08-19 18:42:3512770 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312771 session_deps_.next_protos = SpdyNextProtos();
[email protected]e3ceb682011-06-28 23:55:4612772
12773 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712774 session_deps_.host_resolver.reset(new MockCachingHostResolver());
mmenkee65e7af2015-10-13 17:16:4212775 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2612776 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12777 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4612778
[email protected]8ddf8322012-02-23 18:08:0612779 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812780 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712781 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4612782
[email protected]cdf8f7e72013-05-23 10:56:4612783 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2312784 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812785 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4612786 scoped_ptr<SpdyFrame> host2_req(
12787 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4612788 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312789 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4612790 };
[email protected]23e482282013-06-14 16:08:0212791 scoped_ptr<SpdyFrame> host1_resp(
12792 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12793 scoped_ptr<SpdyFrame> host1_resp_body(
12794 spdy_util_.ConstructSpdyBodyFrame(1, true));
12795 scoped_ptr<SpdyFrame> host2_resp(
12796 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12797 scoped_ptr<SpdyFrame> host2_resp_body(
12798 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4612799 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312800 CreateMockRead(*host1_resp, 1),
12801 CreateMockRead(*host1_resp_body, 2),
12802 CreateMockRead(*host2_resp, 4),
12803 CreateMockRead(*host2_resp_body, 5),
12804 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4612805 };
12806
[email protected]d2b5f092012-06-08 23:55:0212807 IPAddressNumber ip;
12808 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
12809 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12810 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312811 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12812 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712813 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4612814
[email protected]aa22b242011-11-16 18:58:2912815 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4612816 HttpRequestInfo request1;
12817 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312818 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4612819 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012820 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612821
[email protected]49639fa2011-12-20 23:22:4112822 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612823 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112824 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612825
12826 const HttpResponseInfo* response = trans1.GetResponseInfo();
12827 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012828 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212829 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612830
12831 std::string response_data;
12832 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12833 EXPECT_EQ("hello!", response_data);
12834
12835 // Preload www.gmail.com into HostCache.
12836 HostPortPair host_port("www.gmail.com", 443);
[email protected]5109c1952013-08-20 18:44:1012837 HostResolver::RequestInfo resolve_info(host_port);
[email protected]e3ceb682011-06-28 23:55:4612838 AddressList ignored;
[email protected]5109c1952013-08-20 18:44:1012839 rv = session_deps_.host_resolver->Resolve(resolve_info,
12840 DEFAULT_PRIORITY,
12841 &ignored,
12842 callback.callback(),
12843 NULL,
12844 BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:4712845 EXPECT_EQ(ERR_IO_PENDING, rv);
12846 rv = callback.WaitForResult();
12847 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:4612848
12849 HttpRequestInfo request2;
12850 request2.method = "GET";
12851 request2.url = GURL("https://www.gmail.com/");
12852 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012853 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612854
[email protected]49639fa2011-12-20 23:22:4112855 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612856 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112857 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612858
12859 response = trans2.GetResponseInfo();
12860 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012861 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212862 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612863 EXPECT_TRUE(response->was_fetched_via_spdy);
12864 EXPECT_TRUE(response->was_npn_negotiated);
12865 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12866 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4612867}
12868
[email protected]23e482282013-06-14 16:08:0212869TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
bnc55ff9da2015-08-19 18:42:3512870 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312871 session_deps_.next_protos = SpdyNextProtos();
[email protected]d2b5f092012-06-08 23:55:0212872
12873 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712874 session_deps_.host_resolver.reset(new MockCachingHostResolver());
mmenkee65e7af2015-10-13 17:16:4212875 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0212876 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12877 pool_peer.DisableDomainAuthenticationVerification();
12878
12879 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812880 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712881 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]d2b5f092012-06-08 23:55:0212882
[email protected]cdf8f7e72013-05-23 10:56:4612883 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2312884 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812885 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4612886 scoped_ptr<SpdyFrame> host2_req(
12887 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0212888 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312889 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0212890 };
[email protected]23e482282013-06-14 16:08:0212891 scoped_ptr<SpdyFrame> host1_resp(
12892 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12893 scoped_ptr<SpdyFrame> host1_resp_body(
12894 spdy_util_.ConstructSpdyBodyFrame(1, true));
12895 scoped_ptr<SpdyFrame> host2_resp(
12896 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12897 scoped_ptr<SpdyFrame> host2_resp_body(
12898 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0212899 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312900 CreateMockRead(*host1_resp, 1),
12901 CreateMockRead(*host1_resp_body, 2),
12902 CreateMockRead(*host2_resp, 4),
12903 CreateMockRead(*host2_resp_body, 5),
12904 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0212905 };
12906
12907 IPAddressNumber ip;
12908 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
12909 IPEndPoint peer_addr = IPEndPoint(ip, 443);
12910 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312911 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12912 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712913 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0212914
12915 TestCompletionCallback callback;
12916 HttpRequestInfo request1;
12917 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312918 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0212919 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012920 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0212921
12922 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
12923 EXPECT_EQ(ERR_IO_PENDING, rv);
12924 EXPECT_EQ(OK, callback.WaitForResult());
12925
12926 const HttpResponseInfo* response = trans1.GetResponseInfo();
12927 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012928 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212929 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0212930
12931 std::string response_data;
12932 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12933 EXPECT_EQ("hello!", response_data);
12934
12935 HttpRequestInfo request2;
12936 request2.method = "GET";
12937 request2.url = GURL("https://www.gmail.com/");
12938 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012939 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0212940
12941 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
12942 EXPECT_EQ(ERR_IO_PENDING, rv);
12943 EXPECT_EQ(OK, callback.WaitForResult());
12944
12945 response = trans2.GetResponseInfo();
12946 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012947 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212948 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0212949 EXPECT_TRUE(response->was_fetched_via_spdy);
12950 EXPECT_TRUE(response->was_npn_negotiated);
12951 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12952 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0212953}
12954
ttuttle859dc7a2015-04-23 19:42:2912955class OneTimeCachingHostResolver : public HostResolver {
[email protected]e3ceb682011-06-28 23:55:4612956 public:
12957 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
12958 : host_port_(host_port) {}
dchengb03027d2014-10-21 12:00:2012959 ~OneTimeCachingHostResolver() override {}
[email protected]e3ceb682011-06-28 23:55:4612960
12961 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
12962
12963 // HostResolver methods:
dchengb03027d2014-10-21 12:00:2012964 int Resolve(const RequestInfo& info,
12965 RequestPriority priority,
12966 AddressList* addresses,
12967 const CompletionCallback& callback,
12968 RequestHandle* out_req,
12969 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4012970 return host_resolver_.Resolve(
[email protected]5109c1952013-08-20 18:44:1012971 info, priority, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:4012972 }
12973
dchengb03027d2014-10-21 12:00:2012974 int ResolveFromCache(const RequestInfo& info,
12975 AddressList* addresses,
12976 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4012977 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
12978 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]98e1cd012011-11-08 15:33:0912979 host_resolver_.GetHostCache()->clear();
[email protected]e3ceb682011-06-28 23:55:4612980 return rv;
12981 }
12982
dchengb03027d2014-10-21 12:00:2012983 void CancelRequest(RequestHandle req) override {
[email protected]e3ceb682011-06-28 23:55:4612984 host_resolver_.CancelRequest(req);
12985 }
12986
[email protected]46da33be2011-07-19 21:58:0412987 MockCachingHostResolver* GetMockHostResolver() {
12988 return &host_resolver_;
12989 }
12990
[email protected]e3ceb682011-06-28 23:55:4612991 private:
12992 MockCachingHostResolver host_resolver_;
12993 const HostPortPair host_port_;
12994};
12995
mmenke5c642132015-06-02 16:05:1312996TEST_P(HttpNetworkTransactionTest,
12997 UseIPConnectionPoolingWithHostCacheExpiration) {
bnc55ff9da2015-08-19 18:42:3512998 session_deps_.use_alternative_services = true;
[email protected]d7599122014-05-24 03:37:2312999 session_deps_.next_protos = SpdyNextProtos();
[email protected]e3ceb682011-06-28 23:55:4613000
13001 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
[email protected]e3ceb682011-06-28 23:55:4613002 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
[email protected]c6bf8152012-12-02 07:43:3413003 HttpNetworkSession::Params params =
[email protected]bb88e1d32013-05-03 23:11:0713004 SpdySessionDependencies::CreateSessionParams(&session_deps_);
[email protected]e3ceb682011-06-28 23:55:4613005 params.host_resolver = &host_resolver;
mmenkee65e7af2015-10-13 17:16:4213006 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2613007 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
13008 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4613009
[email protected]8ddf8322012-02-23 18:08:0613010 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813011 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713012 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4613013
[email protected]cdf8f7e72013-05-23 10:56:4613014 scoped_ptr<SpdyFrame> host1_req(
bncce36dca22015-04-21 22:11:2313015 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3813016 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4613017 scoped_ptr<SpdyFrame> host2_req(
13018 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4613019 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1313020 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4613021 };
[email protected]23e482282013-06-14 16:08:0213022 scoped_ptr<SpdyFrame> host1_resp(
13023 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13024 scoped_ptr<SpdyFrame> host1_resp_body(
13025 spdy_util_.ConstructSpdyBodyFrame(1, true));
13026 scoped_ptr<SpdyFrame> host2_resp(
13027 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13028 scoped_ptr<SpdyFrame> host2_resp_body(
13029 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4613030 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1313031 CreateMockRead(*host1_resp, 1),
13032 CreateMockRead(*host1_resp_body, 2),
13033 CreateMockRead(*host2_resp, 4),
13034 CreateMockRead(*host2_resp_body, 5),
13035 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4613036 };
13037
[email protected]d2b5f092012-06-08 23:55:0213038 IPAddressNumber ip;
13039 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
13040 IPEndPoint peer_addr = IPEndPoint(ip, 443);
13041 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1313042 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
13043 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0713044 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4613045
[email protected]aa22b242011-11-16 18:58:2913046 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4613047 HttpRequestInfo request1;
13048 request1.method = "GET";
bncce36dca22015-04-21 22:11:2313049 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4613050 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013051 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4613052
[email protected]49639fa2011-12-20 23:22:4113053 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4613054 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4113055 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4613056
13057 const HttpResponseInfo* response = trans1.GetResponseInfo();
13058 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013059 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0213060 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4613061
13062 std::string response_data;
13063 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
13064 EXPECT_EQ("hello!", response_data);
13065
13066 // Preload cache entries into HostCache.
[email protected]5109c1952013-08-20 18:44:1013067 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
[email protected]e3ceb682011-06-28 23:55:4613068 AddressList ignored;
[email protected]5109c1952013-08-20 18:44:1013069 rv = host_resolver.Resolve(resolve_info,
13070 DEFAULT_PRIORITY,
13071 &ignored,
13072 callback.callback(),
13073 NULL,
13074 BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:4713075 EXPECT_EQ(ERR_IO_PENDING, rv);
13076 rv = callback.WaitForResult();
13077 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:4613078
13079 HttpRequestInfo request2;
13080 request2.method = "GET";
13081 request2.url = GURL("https://www.gmail.com/");
13082 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013083 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4613084
[email protected]49639fa2011-12-20 23:22:4113085 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4613086 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4113087 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4613088
13089 response = trans2.GetResponseInfo();
13090 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013091 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0213092 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4613093 EXPECT_TRUE(response->was_fetched_via_spdy);
13094 EXPECT_TRUE(response->was_npn_negotiated);
13095 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
13096 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4613097}
13098
[email protected]23e482282013-06-14 16:08:0213099TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2313100 const std::string https_url = "https://www.example.org:8080/";
13101 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0413102
13103 // SPDY GET for HTTPS URL
[email protected]cdf8f7e72013-05-23 10:56:4613104 scoped_ptr<SpdyFrame> req1(
13105 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0413106
13107 MockWrite writes1[] = {
13108 CreateMockWrite(*req1, 0),
13109 };
13110
[email protected]23e482282013-06-14 16:08:0213111 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13112 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
mmenkee24011922015-12-17 22:12:5913113 MockRead reads1[] = {CreateMockRead(*resp1, 1), CreateMockRead(*body1, 2),
13114 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0413115
rch8e6c6c42015-05-01 14:05:1313116 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
13117 arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0413118 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5713119 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0413120
13121 // HTTP GET for the HTTP URL
13122 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1313123 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3413124 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2313125 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3413126 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0413127 };
13128
13129 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1313130 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
13131 MockRead(ASYNC, 2, "hello"),
13132 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0413133 };
13134
rch8e6c6c42015-05-01 14:05:1313135 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13136 arraysize(writes2));
[email protected]8450d722012-07-02 19:14:0413137
[email protected]8450d722012-07-02 19:14:0413138 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813139 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713140 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13141 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13142 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0413143
mmenkee65e7af2015-10-13 17:16:4213144 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0413145
13146 // Start the first transaction to set up the SpdySession
13147 HttpRequestInfo request1;
13148 request1.method = "GET";
13149 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0413150 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013151 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0413152 TestCompletionCallback callback1;
13153 EXPECT_EQ(ERR_IO_PENDING,
13154 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413155 base::MessageLoop::current()->RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0413156
13157 EXPECT_EQ(OK, callback1.WaitForResult());
13158 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13159
13160 // Now, start the HTTP request
13161 HttpRequestInfo request2;
13162 request2.method = "GET";
13163 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0413164 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013165 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0413166 TestCompletionCallback callback2;
13167 EXPECT_EQ(ERR_IO_PENDING,
13168 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413169 base::MessageLoop::current()->RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0413170
13171 EXPECT_EQ(OK, callback2.WaitForResult());
13172 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13173}
13174
bnc1b0e36852015-04-28 15:32:5913175class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
13176 public:
13177 void Run(bool pooling, bool valid) {
13178 HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org",
13179 443);
13180 HostPortPair alternative("www.example.org", 443);
13181
13182 base::FilePath certs_dir = GetTestCertsDirectory();
13183 scoped_refptr<X509Certificate> cert(
13184 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
13185 ASSERT_TRUE(cert.get());
13186 bool common_name_fallback_used;
13187 EXPECT_EQ(valid,
13188 cert->VerifyNameMatch(origin.host(), &common_name_fallback_used));
13189 EXPECT_TRUE(
13190 cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used));
13191 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813192 ssl.SetNextProto(GetProtocol());
bnc1b0e36852015-04-28 15:32:5913193 ssl.cert = cert;
13194 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13195
13196 // If pooling, then start a request to alternative first to create a
13197 // SpdySession.
13198 std::string url0 = "https://www.example.org:443";
13199 // Second request to origin, which has an alternative service, and could
13200 // open a connection to the alternative host or pool to the existing one.
13201 std::string url1("https://");
13202 url1.append(origin.host());
13203 url1.append(":443");
13204
13205 scoped_ptr<SpdyFrame> req0;
13206 scoped_ptr<SpdyFrame> req1;
13207 scoped_ptr<SpdyFrame> resp0;
13208 scoped_ptr<SpdyFrame> body0;
13209 scoped_ptr<SpdyFrame> resp1;
13210 scoped_ptr<SpdyFrame> body1;
13211 std::vector<MockWrite> writes;
13212 std::vector<MockRead> reads;
13213
13214 if (pooling) {
13215 req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), false, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3813216 spdy_util_.UpdateWithStreamDestruction(1);
bnc1b0e36852015-04-28 15:32:5913217 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 3, LOWEST));
13218
13219 writes.push_back(CreateMockWrite(*req0, 0));
13220 writes.push_back(CreateMockWrite(*req1, 3));
13221
13222 resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13223 body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
13224 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13225 body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true));
13226
13227 reads.push_back(CreateMockRead(*resp0, 1));
13228 reads.push_back(CreateMockRead(*body0, 2));
13229 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4));
13230 reads.push_back(CreateMockRead(*resp1, 5));
13231 reads.push_back(CreateMockRead(*body1, 6));
13232 reads.push_back(MockRead(ASYNC, OK, 7));
13233 } else {
13234 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 1, LOWEST));
13235
13236 writes.push_back(CreateMockWrite(*req1, 0));
13237
13238 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13239 body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
13240
13241 reads.push_back(CreateMockRead(*resp1, 1));
13242 reads.push_back(CreateMockRead(*body1, 2));
13243 reads.push_back(MockRead(ASYNC, OK, 3));
13244 }
13245
davidben5f8b6bc2015-11-25 03:19:5413246 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
13247 writes.size());
bnc1b0e36852015-04-28 15:32:5913248 session_deps_.socket_factory->AddSocketDataProvider(&data);
13249
13250 // Connection to the origin fails.
13251 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13252 StaticSocketDataProvider data_refused;
13253 data_refused.set_connect_data(mock_connect);
13254 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13255
bnc55ff9da2015-08-19 18:42:3513256 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213257 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc1b0e36852015-04-28 15:32:5913258 base::WeakPtr<HttpServerProperties> http_server_properties =
13259 session->http_server_properties();
13260 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813261 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213262 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc1b0e36852015-04-28 15:32:5913263 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213264 1.0, expiration);
bnc1b0e36852015-04-28 15:32:5913265
13266 // First request to alternative.
13267 if (pooling) {
13268 scoped_ptr<HttpTransaction> trans0(
13269 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13270 HttpRequestInfo request0;
13271 request0.method = "GET";
13272 request0.url = GURL(url0);
13273 request0.load_flags = 0;
13274 TestCompletionCallback callback0;
13275
13276 int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog());
13277 EXPECT_EQ(ERR_IO_PENDING, rv);
13278 rv = callback0.WaitForResult();
13279 EXPECT_EQ(OK, rv);
13280 }
13281
13282 // Second request to origin.
13283 scoped_ptr<HttpTransaction> trans1(
13284 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13285 HttpRequestInfo request1;
13286 request1.method = "GET";
13287 request1.url = GURL(url1);
13288 request1.load_flags = 0;
13289 TestCompletionCallback callback1;
13290
13291 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
13292 EXPECT_EQ(ERR_IO_PENDING, rv);
rch32320842015-05-16 15:57:0913293 base::MessageLoop::current()->RunUntilIdle();
mmenkee24011922015-12-17 22:12:5913294 if (data.IsPaused())
13295 data.Resume();
bnc1b0e36852015-04-28 15:32:5913296 rv = callback1.WaitForResult();
13297 if (valid) {
13298 EXPECT_EQ(OK, rv);
13299 } else {
13300 if (pooling) {
13301 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
13302 } else {
13303 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv);
13304 }
13305 }
13306 }
13307};
13308
rdsmithebb50aa2015-11-12 03:44:3813309INSTANTIATE_TEST_CASE_P(ProtoPlusDepend,
bnc1b0e36852015-04-28 15:32:5913310 AltSvcCertificateVerificationTest,
rdsmithebb50aa2015-11-12 03:44:3813311 testing::Values(kTestCaseSPDY31,
13312 kTestCaseHTTP2NoPriorityDependencies,
13313 kTestCaseHTTP2PriorityDependencies));
bnc1b0e36852015-04-28 15:32:5913314
13315// The alternative service host must exhibit a certificate that is valid for the
13316// origin host. Test that this is enforced when pooling to an existing
13317// connection.
13318TEST_P(AltSvcCertificateVerificationTest, PoolingValid) {
13319 Run(true, true);
13320}
13321
13322TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) {
13323 Run(true, false);
13324}
13325
13326// The alternative service host must exhibit a certificate that is valid for the
13327// origin host. Test that this is enforced when opening a new connection.
13328TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) {
13329 Run(false, true);
13330}
13331
13332TEST_P(AltSvcCertificateVerificationTest, NewConnectionInvalid) {
13333 Run(false, false);
13334}
13335
bnc5452e2a2015-05-08 16:27:4213336// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
13337// with the alternative server. That connection should not be used.
13338TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
13339 HostPortPair origin("origin.example.org", 443);
13340 HostPortPair alternative("alternative.example.org", 443);
13341
13342 // Negotiate HTTP/1.1 with alternative.example.org.
13343 SSLSocketDataProvider ssl(ASYNC, OK);
13344 ssl.SetNextProto(kProtoHTTP11);
13345 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13346
13347 // No data should be read from the alternative, because HTTP/1.1 is
13348 // negotiated.
13349 StaticSocketDataProvider data;
13350 session_deps_.socket_factory->AddSocketDataProvider(&data);
13351
13352 // This test documents that an alternate Job should not be used if HTTP/1.1 is
13353 // negotiated. In order to test this, a failed connection to the origin is
13354 // mocked. This way the request relies on the alternate Job.
13355 StaticSocketDataProvider data_refused;
13356 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13357 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13358
13359 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3513360 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213361 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc5452e2a2015-05-08 16:27:4213362 base::WeakPtr<HttpServerProperties> http_server_properties =
13363 session->http_server_properties();
13364 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813365 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213366 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc5452e2a2015-05-08 16:27:4213367 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213368 1.0, expiration);
bnc5452e2a2015-05-08 16:27:4213369
13370 scoped_ptr<HttpTransaction> trans(
13371 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13372 HttpRequestInfo request;
13373 request.method = "GET";
13374 request.url = GURL("https://origin.example.org:443");
13375 request.load_flags = 0;
13376 TestCompletionCallback callback;
13377
13378 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
13379 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
13380 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13381 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED, callback.GetResult(rv));
13382}
13383
bnc40448a532015-05-11 19:13:1413384// A request to a server with an alternative service fires two Jobs: one to the
13385// origin, and an alternate one to the alternative server. If the former
13386// succeeds, the request should succeed, even if the latter fails because
13387// HTTP/1.1 is negotiated which is insufficient for alternative service.
13388TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
13389 HostPortPair origin("origin.example.org", 443);
13390 HostPortPair alternative("alternative.example.org", 443);
13391
13392 // Negotiate HTTP/1.1 with alternative.
13393 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
13394 alternative_ssl.SetNextProto(kProtoHTTP11);
13395 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
13396
13397 // No data should be read from the alternative, because HTTP/1.1 is
13398 // negotiated.
13399 StaticSocketDataProvider data;
13400 session_deps_.socket_factory->AddSocketDataProvider(&data);
13401
13402 // Negotiate HTTP/1.1 with origin.
13403 SSLSocketDataProvider origin_ssl(ASYNC, OK);
13404 origin_ssl.SetNextProto(kProtoHTTP11);
13405 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
13406
13407 MockWrite http_writes[] = {
13408 MockWrite(
13409 "GET / HTTP/1.1\r\n"
13410 "Host: origin.example.org\r\n"
13411 "Connection: keep-alive\r\n\r\n"),
13412 MockWrite(
13413 "GET /second HTTP/1.1\r\n"
13414 "Host: origin.example.org\r\n"
13415 "Connection: keep-alive\r\n\r\n"),
13416 };
13417
13418 MockRead http_reads[] = {
13419 MockRead("HTTP/1.1 200 OK\r\n"),
13420 MockRead("Content-Type: text/html\r\n"),
13421 MockRead("Content-Length: 6\r\n\r\n"),
13422 MockRead("foobar"),
13423 MockRead("HTTP/1.1 200 OK\r\n"),
13424 MockRead("Content-Type: text/html\r\n"),
13425 MockRead("Content-Length: 7\r\n\r\n"),
13426 MockRead("another"),
13427 };
13428 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13429 http_writes, arraysize(http_writes));
13430 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13431
13432 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3513433 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213434 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc40448a532015-05-11 19:13:1413435 base::WeakPtr<HttpServerProperties> http_server_properties =
13436 session->http_server_properties();
13437 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813438 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213439 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc40448a532015-05-11 19:13:1413440 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213441 1.0, expiration);
bnc40448a532015-05-11 19:13:1413442
13443 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
13444 HttpRequestInfo request1;
13445 request1.method = "GET";
13446 request1.url = GURL("https://origin.example.org:443");
13447 request1.load_flags = 0;
13448 TestCompletionCallback callback1;
13449
13450 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
13451 rv = callback1.GetResult(rv);
13452 EXPECT_EQ(OK, rv);
13453
13454 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
13455 ASSERT_TRUE(response1 != nullptr);
13456 ASSERT_TRUE(response1->headers.get() != nullptr);
13457 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13458
13459 std::string response_data1;
13460 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data1));
13461 EXPECT_EQ("foobar", response_data1);
13462
13463 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
13464 // for alternative service.
13465 EXPECT_TRUE(
13466 http_server_properties->IsAlternativeServiceBroken(alternative_service));
13467
13468 // Since |alternative_service| is broken, a second transaction to origin
13469 // should not start an alternate Job. It should pool to existing connection
13470 // to origin.
13471 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
13472 HttpRequestInfo request2;
13473 request2.method = "GET";
13474 request2.url = GURL("https://origin.example.org:443/second");
13475 request2.load_flags = 0;
13476 TestCompletionCallback callback2;
13477
13478 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
13479 rv = callback2.GetResult(rv);
13480 EXPECT_EQ(OK, rv);
13481
13482 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
13483 ASSERT_TRUE(response2 != nullptr);
13484 ASSERT_TRUE(response2->headers.get() != nullptr);
13485 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
13486
13487 std::string response_data2;
13488 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data2));
13489 EXPECT_EQ("another", response_data2);
13490}
13491
bnc5452e2a2015-05-08 16:27:4213492// Alternative service requires HTTP/2 (or SPDY), but there is already a
13493// HTTP/1.1 socket open to the alternative server. That socket should not be
13494// used.
13495TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
13496 HostPortPair origin("origin.example.org", 443);
13497 HostPortPair alternative("alternative.example.org", 443);
13498 std::string origin_url = "https://origin.example.org:443";
13499 std::string alternative_url = "https://alternative.example.org:443";
13500
13501 // Negotiate HTTP/1.1 with alternative.example.org.
13502 SSLSocketDataProvider ssl(ASYNC, OK);
13503 ssl.SetNextProto(kProtoHTTP11);
13504 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13505
13506 // HTTP/1.1 data for |request1| and |request2|.
13507 MockWrite http_writes[] = {
13508 MockWrite(
13509 "GET / HTTP/1.1\r\n"
13510 "Host: alternative.example.org\r\n"
13511 "Connection: keep-alive\r\n\r\n"),
13512 MockWrite(
13513 "GET / HTTP/1.1\r\n"
13514 "Host: alternative.example.org\r\n"
13515 "Connection: keep-alive\r\n\r\n"),
13516 };
13517
13518 MockRead http_reads[] = {
13519 MockRead(
13520 "HTTP/1.1 200 OK\r\n"
13521 "Content-Type: text/html; charset=iso-8859-1\r\n"
13522 "Content-Length: 40\r\n\r\n"
13523 "first HTTP/1.1 response from alternative"),
13524 MockRead(
13525 "HTTP/1.1 200 OK\r\n"
13526 "Content-Type: text/html; charset=iso-8859-1\r\n"
13527 "Content-Length: 41\r\n\r\n"
13528 "second HTTP/1.1 response from alternative"),
13529 };
13530 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13531 http_writes, arraysize(http_writes));
13532 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13533
13534 // This test documents that an alternate Job should not pool to an already
13535 // existing HTTP/1.1 connection. In order to test this, a failed connection
13536 // to the origin is mocked. This way |request2| relies on the alternate Job.
13537 StaticSocketDataProvider data_refused;
13538 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13539 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13540
13541 // Set up alternative service for origin.
bnc55ff9da2015-08-19 18:42:3513542 session_deps_.use_alternative_services = true;
mmenkee65e7af2015-10-13 17:16:4213543 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc5452e2a2015-05-08 16:27:4213544 base::WeakPtr<HttpServerProperties> http_server_properties =
13545 session->http_server_properties();
13546 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813547 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213548 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc5452e2a2015-05-08 16:27:4213549 http_server_properties->SetAlternativeService(origin, alternative_service,
bnc7dc7e1b42015-07-28 14:43:1213550 1.0, expiration);
bnc5452e2a2015-05-08 16:27:4213551
13552 // First transaction to alternative to open an HTTP/1.1 socket.
13553 scoped_ptr<HttpTransaction> trans1(
13554 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13555 HttpRequestInfo request1;
13556 request1.method = "GET";
13557 request1.url = GURL(alternative_url);
13558 request1.load_flags = 0;
13559 TestCompletionCallback callback1;
13560
13561 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
13562 EXPECT_EQ(OK, callback1.GetResult(rv));
13563 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
13564 ASSERT_TRUE(response1);
13565 ASSERT_TRUE(response1->headers.get());
13566 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13567 EXPECT_TRUE(response1->was_npn_negotiated);
13568 EXPECT_FALSE(response1->was_fetched_via_spdy);
13569 std::string response_data1;
13570 ASSERT_EQ(OK, ReadTransaction(trans1.get(), &response_data1));
13571 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
13572
13573 // Request for origin.example.org, which has an alternative service. This
13574 // will start two Jobs: the alternative looks for connections to pool to,
13575 // finds one which is HTTP/1.1, and should ignore it, and should not try to
13576 // open other connections to alternative server. The Job to origin fails, so
13577 // this request fails.
13578 scoped_ptr<HttpTransaction> trans2(
13579 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13580 HttpRequestInfo request2;
13581 request2.method = "GET";
13582 request2.url = GURL(origin_url);
13583 request2.load_flags = 0;
13584 TestCompletionCallback callback2;
13585
13586 rv = trans2->Start(&request2, callback2.callback(), BoundNetLog());
13587 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback2.GetResult(rv));
13588
13589 // Another transaction to alternative. This is to test that the HTTP/1.1
13590 // socket is still open and in the pool.
13591 scoped_ptr<HttpTransaction> trans3(
13592 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13593 HttpRequestInfo request3;
13594 request3.method = "GET";
13595 request3.url = GURL(alternative_url);
13596 request3.load_flags = 0;
13597 TestCompletionCallback callback3;
13598
13599 rv = trans3->Start(&request3, callback3.callback(), BoundNetLog());
13600 EXPECT_EQ(OK, callback3.GetResult(rv));
13601 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
13602 ASSERT_TRUE(response3);
13603 ASSERT_TRUE(response3->headers.get());
13604 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
13605 EXPECT_TRUE(response3->was_npn_negotiated);
13606 EXPECT_FALSE(response3->was_fetched_via_spdy);
13607 std::string response_data3;
13608 ASSERT_EQ(OK, ReadTransaction(trans3.get(), &response_data3));
13609 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
13610}
13611
[email protected]23e482282013-06-14 16:08:0213612TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2313613 const std::string https_url = "https://www.example.org:8080/";
13614 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0413615
rdsmithebb50aa2015-11-12 03:44:3813616 // Separate SPDY util instance for naked and wrapped requests.
13617 SpdyTestUtil spdy_util_wrapped(GetProtocol(), GetDependenciesFromPriority());
13618
[email protected]8450d722012-07-02 19:14:0413619 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2313620 const HostPortPair host_port_pair("www.example.org", 8080);
lgarrona91df87f2014-12-05 00:51:3413621 scoped_ptr<SpdyFrame> connect(
13622 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
[email protected]cdf8f7e72013-05-23 10:56:4613623 scoped_ptr<SpdyFrame> req1(
rdsmithebb50aa2015-11-12 03:44:3813624 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
[email protected]23e482282013-06-14 16:08:0213625 scoped_ptr<SpdyFrame> wrapped_req1(
13626 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3913627
13628 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
[email protected]745aa9c2014-06-27 02:21:2913629 SpdyHeaderBlock req2_block;
bnc7ecc1122015-09-28 13:22:4913630 spdy_util_.MaybeAddVersionHeader(&req2_block);
[email protected]745aa9c2014-06-27 02:21:2913631 req2_block[spdy_util_.GetMethodKey()] = "GET";
bncce36dca22015-04-21 22:11:2313632 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
[email protected]745aa9c2014-06-27 02:21:2913633 req2_block[spdy_util_.GetSchemeKey()] = "http";
bnc7ecc1122015-09-28 13:22:4913634 req2_block[spdy_util_.GetPathKey()] = "/";
[email protected]601e03f12014-04-06 16:26:3913635 scoped_ptr<SpdyFrame> req2(
[email protected]745aa9c2014-06-27 02:21:2913636 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
[email protected]8450d722012-07-02 19:14:0413637
13638 MockWrite writes1[] = {
mmenke666a6fea2015-12-19 04:16:3313639 CreateMockWrite(*connect, 0), CreateMockWrite(*wrapped_req1, 2),
13640 CreateMockWrite(*req2, 6),
[email protected]8450d722012-07-02 19:14:0413641 };
13642
[email protected]23e482282013-06-14 16:08:0213643 scoped_ptr<SpdyFrame> conn_resp(
13644 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13645 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13646 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
13647 scoped_ptr<SpdyFrame> wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3813648 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
[email protected]23e482282013-06-14 16:08:0213649 scoped_ptr<SpdyFrame> wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3813650 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
[email protected]23e482282013-06-14 16:08:0213651 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13652 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3313653 MockRead reads1[] = {
13654 CreateMockRead(*conn_resp, 1),
13655 MockRead(ASYNC, ERR_IO_PENDING, 3),
13656 CreateMockRead(*wrapped_resp1, 4),
13657 CreateMockRead(*wrapped_body1, 5),
13658 MockRead(ASYNC, ERR_IO_PENDING, 7),
13659 CreateMockRead(*resp2, 8),
13660 CreateMockRead(*body2, 9),
13661 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
13662 };
[email protected]8450d722012-07-02 19:14:0413663
mmenke666a6fea2015-12-19 04:16:3313664 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
13665 arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0413666 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5713667 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0413668
rdsmith82957ad2015-09-16 19:42:0313669 session_deps_.proxy_service =
13670 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:5113671 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0713672 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0413673 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
rdsmithebb50aa2015-11-12 03:44:3813674 ssl1.SetNextProto(GetProtocol());
mmenke666a6fea2015-12-19 04:16:3313675 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0413676 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
rdsmithebb50aa2015-11-12 03:44:3813677 ssl2.SetNextProto(GetProtocol());
mmenke666a6fea2015-12-19 04:16:3313678 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13679 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0413680
mmenke666a6fea2015-12-19 04:16:3313681 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0413682
13683 // Start the first transaction to set up the SpdySession
13684 HttpRequestInfo request1;
13685 request1.method = "GET";
13686 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0413687 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013688 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0413689 TestCompletionCallback callback1;
mmenke666a6fea2015-12-19 04:16:3313690 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
[email protected]8450d722012-07-02 19:14:0413691
mmenke666a6fea2015-12-19 04:16:3313692 // This pause is a hack to avoid running into https://crbug.com/497228.
13693 data1.RunUntilPaused();
13694 base::RunLoop().RunUntilIdle();
13695 data1.Resume();
13696 EXPECT_EQ(OK, callback1.GetResult(rv));
[email protected]8450d722012-07-02 19:14:0413697 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13698
[email protected]f6c63db52013-02-02 00:35:2213699 LoadTimingInfo load_timing_info1;
13700 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
13701 TestLoadTimingNotReusedWithPac(load_timing_info1,
13702 CONNECT_TIMING_HAS_SSL_TIMES);
13703
mmenke666a6fea2015-12-19 04:16:3313704 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0413705 HttpRequestInfo request2;
13706 request2.method = "GET";
13707 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0413708 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013709 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0413710 TestCompletionCallback callback2;
mmenke666a6fea2015-12-19 04:16:3313711 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
[email protected]8450d722012-07-02 19:14:0413712
mmenke666a6fea2015-12-19 04:16:3313713 // This pause is a hack to avoid running into https://crbug.com/497228.
13714 data1.RunUntilPaused();
13715 base::RunLoop().RunUntilIdle();
13716 data1.Resume();
13717 EXPECT_EQ(OK, callback2.GetResult(rv));
13718
[email protected]8450d722012-07-02 19:14:0413719 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2213720
13721 LoadTimingInfo load_timing_info2;
13722 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
13723 // The established SPDY sessions is considered reused by the HTTP request.
13724 TestLoadTimingReusedWithPac(load_timing_info2);
13725 // HTTP requests over a SPDY session should have a different connection
13726 // socket_log_id than requests over a tunnel.
13727 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0413728}
13729
[email protected]2d88e7d2012-07-19 17:55:1713730// Test that in the case where we have a SPDY session to a SPDY proxy
13731// that we do not pool other origins that resolve to the same IP when
13732// the certificate does not match the new origin.
13733// http://crbug.com/134690
[email protected]23e482282013-06-14 16:08:0213734TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2313735 const std::string url1 = "http://www.example.org/";
13736 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1713737 const std::string ip_addr = "1.2.3.4";
13738
rdsmithebb50aa2015-11-12 03:44:3813739 // Second SpdyTestUtil instance for the second socket.
13740 SpdyTestUtil spdy_util_secure(GetProtocol(), GetDependenciesFromPriority());
13741
[email protected]2d88e7d2012-07-19 17:55:1713742 // SPDY GET for HTTP URL (through SPDY proxy)
[email protected]23e482282013-06-14 16:08:0213743 scoped_ptr<SpdyHeaderBlock> headers(
bncce36dca22015-04-21 22:11:2313744 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
[email protected]745aa9c2014-06-27 02:21:2913745 scoped_ptr<SpdyFrame> req1(
13746 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]2d88e7d2012-07-19 17:55:1713747
13748 MockWrite writes1[] = {
13749 CreateMockWrite(*req1, 0),
13750 };
13751
[email protected]23e482282013-06-14 16:08:0213752 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13753 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1713754 MockRead reads1[] = {
mmenke666a6fea2015-12-19 04:16:3313755 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(*resp1, 2),
13756 CreateMockRead(*body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1713757 };
13758
mmenke666a6fea2015-12-19 04:16:3313759 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
13760 arraysize(writes1));
[email protected]2d88e7d2012-07-19 17:55:1713761 IPAddressNumber ip;
13762 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
13763 IPEndPoint peer_addr = IPEndPoint(ip, 443);
13764 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3313765 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1713766
13767 // SPDY GET for HTTPS URL (direct)
[email protected]cdf8f7e72013-05-23 10:56:4613768 scoped_ptr<SpdyFrame> req2(
rdsmithebb50aa2015-11-12 03:44:3813769 spdy_util_secure.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1713770
13771 MockWrite writes2[] = {
13772 CreateMockWrite(*req2, 0),
13773 };
13774
rdsmithebb50aa2015-11-12 03:44:3813775 scoped_ptr<SpdyFrame> resp2(
13776 spdy_util_secure.ConstructSpdyGetSynReply(NULL, 0, 1));
13777 scoped_ptr<SpdyFrame> body2(spdy_util_secure.ConstructSpdyBodyFrame(1, true));
mmenke666a6fea2015-12-19 04:16:3313778 MockRead reads2[] = {CreateMockRead(*resp2, 1), CreateMockRead(*body2, 2),
13779 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1713780
mmenke666a6fea2015-12-19 04:16:3313781 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13782 arraysize(writes2));
[email protected]2d88e7d2012-07-19 17:55:1713783 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3313784 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1713785
13786 // Set up a proxy config that sends HTTP requests to a proxy, and
13787 // all others direct.
13788 ProxyConfig proxy_config;
13789 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
[email protected]bb88e1d32013-05-03 23:11:0713790 session_deps_.proxy_service.reset(new ProxyService(
csharrisonb7e3a082015-09-22 19:13:0413791 make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)), nullptr,
13792 NULL));
[email protected]2d88e7d2012-07-19 17:55:1713793
bncce36dca22015-04-21 22:11:2313794 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
rdsmithebb50aa2015-11-12 03:44:3813795 ssl1.SetNextProto(GetProtocol());
[email protected]2d88e7d2012-07-19 17:55:1713796 // Load a valid cert. Note, that this does not need to
13797 // be valid for proxy because the MockSSLClientSocket does
13798 // not actually verify it. But SpdySession will use this
13799 // to see if it is valid for the new origin
bncce36dca22015-04-21 22:11:2313800 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
13801 ASSERT_TRUE(ssl1.cert.get());
mmenke666a6fea2015-12-19 04:16:3313802 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13803 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1713804
13805 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
rdsmithebb50aa2015-11-12 03:44:3813806 ssl2.SetNextProto(GetProtocol());
mmenke666a6fea2015-12-19 04:16:3313807 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13808 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1713809
[email protected]bb88e1d32013-05-03 23:11:0713810 session_deps_.host_resolver.reset(new MockCachingHostResolver());
bncce36dca22015-04-21 22:11:2313811 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0713812 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1713813
mmenke666a6fea2015-12-19 04:16:3313814 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1713815
13816 // Start the first transaction to set up the SpdySession
13817 HttpRequestInfo request1;
13818 request1.method = "GET";
13819 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1713820 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013821 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713822 TestCompletionCallback callback1;
13823 ASSERT_EQ(ERR_IO_PENDING,
13824 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
mmenke666a6fea2015-12-19 04:16:3313825 // This pause is a hack to avoid running into https://crbug.com/497228.
13826 data1.RunUntilPaused();
13827 base::RunLoop().RunUntilIdle();
13828 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1713829
[email protected]2d88e7d2012-07-19 17:55:1713830 EXPECT_EQ(OK, callback1.WaitForResult());
13831 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13832
13833 // Now, start the HTTP request
13834 HttpRequestInfo request2;
13835 request2.method = "GET";
13836 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1713837 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013838 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713839 TestCompletionCallback callback2;
13840 EXPECT_EQ(ERR_IO_PENDING,
13841 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413842 base::MessageLoop::current()->RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1713843
13844 ASSERT_TRUE(callback2.have_result());
13845 EXPECT_EQ(OK, callback2.WaitForResult());
13846 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13847}
13848
[email protected]85f97342013-04-17 06:12:2413849// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
13850// error) in SPDY session, removes the socket from pool and closes the SPDY
13851// session. Verify that new url's from the same HttpNetworkSession (and a new
13852// SpdySession) do work. http://crbug.com/224701
[email protected]23e482282013-06-14 16:08:0213853TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2313854 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2413855
13856 MockRead reads1[] = {
13857 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
13858 };
13859
mmenke11eb5152015-06-09 14:50:5013860 SequencedSocketData data1(reads1, arraysize(reads1), NULL, 0);
[email protected]85f97342013-04-17 06:12:2413861
[email protected]cdf8f7e72013-05-23 10:56:4613862 scoped_ptr<SpdyFrame> req2(
13863 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2413864 MockWrite writes2[] = {
13865 CreateMockWrite(*req2, 0),
13866 };
13867
[email protected]23e482282013-06-14 16:08:0213868 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13869 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]85f97342013-04-17 06:12:2413870 MockRead reads2[] = {
13871 CreateMockRead(*resp2, 1),
13872 CreateMockRead(*body2, 2),
13873 MockRead(ASYNC, OK, 3) // EOF
13874 };
13875
mmenke11eb5152015-06-09 14:50:5013876 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13877 arraysize(writes2));
[email protected]85f97342013-04-17 06:12:2413878
[email protected]85f97342013-04-17 06:12:2413879 SSLSocketDataProvider ssl1(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813880 ssl1.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:5013881 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13882 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2413883
13884 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813885 ssl2.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:5013886 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13887 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2413888
mmenkee65e7af2015-10-13 17:16:4213889 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5013890 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2413891
13892 // Start the first transaction to set up the SpdySession and verify that
13893 // connection was closed.
13894 HttpRequestInfo request1;
13895 request1.method = "GET";
13896 request1.url = GURL(https_url);
13897 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013898 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2413899 TestCompletionCallback callback1;
13900 EXPECT_EQ(ERR_IO_PENDING,
13901 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]85f97342013-04-17 06:12:2413902 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
13903
13904 // Now, start the second request and make sure it succeeds.
13905 HttpRequestInfo request2;
13906 request2.method = "GET";
13907 request2.url = GURL(https_url);
13908 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013909 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2413910 TestCompletionCallback callback2;
13911 EXPECT_EQ(ERR_IO_PENDING,
13912 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]85f97342013-04-17 06:12:2413913
mmenke11eb5152015-06-09 14:50:5013914 ASSERT_EQ(OK, callback2.WaitForResult());
[email protected]85f97342013-04-17 06:12:2413915 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13916}
13917
[email protected]23e482282013-06-14 16:08:0213918TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]d7599122014-05-24 03:37:2313919 session_deps_.next_protos = SpdyNextProtos();
[email protected]483fa202013-05-14 01:07:0313920 ClientSocketPoolManager::set_max_sockets_per_group(
13921 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13922 ClientSocketPoolManager::set_max_sockets_per_pool(
13923 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13924
13925 // Use two different hosts with different IPs so they don't get pooled.
13926 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
13927 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
mmenkee65e7af2015-10-13 17:16:4213928 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0313929
13930 SSLSocketDataProvider ssl1(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813931 ssl1.SetNextProto(GetProtocol());
[email protected]483fa202013-05-14 01:07:0313932 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813933 ssl2.SetNextProto(GetProtocol());
[email protected]483fa202013-05-14 01:07:0313934 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13935 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13936
[email protected]cdf8f7e72013-05-23 10:56:4613937 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
[email protected]483fa202013-05-14 01:07:0313938 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
13939 MockWrite spdy1_writes[] = {
rch8e6c6c42015-05-01 14:05:1313940 CreateMockWrite(*host1_req, 0),
[email protected]483fa202013-05-14 01:07:0313941 };
[email protected]23e482282013-06-14 16:08:0213942 scoped_ptr<SpdyFrame> host1_resp(
13943 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13944 scoped_ptr<SpdyFrame> host1_resp_body(
13945 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]483fa202013-05-14 01:07:0313946 MockRead spdy1_reads[] = {
mmenkee24011922015-12-17 22:12:5913947 CreateMockRead(*host1_resp, 1), CreateMockRead(*host1_resp_body, 2),
13948 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0313949 };
13950
rdsmithebb50aa2015-11-12 03:44:3813951 // Use a separate test instance for the separate SpdySession that will be
13952 // created.
13953 SpdyTestUtil spdy_util_2(GetProtocol(), GetDependenciesFromPriority());
rch8e6c6c42015-05-01 14:05:1313954 scoped_ptr<SequencedSocketData> spdy1_data(
13955 new SequencedSocketData(spdy1_reads, arraysize(spdy1_reads), spdy1_writes,
13956 arraysize(spdy1_writes)));
[email protected]483fa202013-05-14 01:07:0313957 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
13958
rdsmithebb50aa2015-11-12 03:44:3813959 scoped_ptr<SpdyFrame> host2_req(spdy_util_2.ConstructSpdyGet(
[email protected]483fa202013-05-14 01:07:0313960 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
13961 MockWrite spdy2_writes[] = {
rch8e6c6c42015-05-01 14:05:1313962 CreateMockWrite(*host2_req, 0),
[email protected]483fa202013-05-14 01:07:0313963 };
[email protected]23e482282013-06-14 16:08:0213964 scoped_ptr<SpdyFrame> host2_resp(
rdsmithebb50aa2015-11-12 03:44:3813965 spdy_util_2.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]23e482282013-06-14 16:08:0213966 scoped_ptr<SpdyFrame> host2_resp_body(
rdsmithebb50aa2015-11-12 03:44:3813967 spdy_util_2.ConstructSpdyBodyFrame(1, true));
[email protected]483fa202013-05-14 01:07:0313968 MockRead spdy2_reads[] = {
mmenkee24011922015-12-17 22:12:5913969 CreateMockRead(*host2_resp, 1), CreateMockRead(*host2_resp_body, 2),
13970 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0313971 };
13972
rch8e6c6c42015-05-01 14:05:1313973 scoped_ptr<SequencedSocketData> spdy2_data(
13974 new SequencedSocketData(spdy2_reads, arraysize(spdy2_reads), spdy2_writes,
13975 arraysize(spdy2_writes)));
[email protected]483fa202013-05-14 01:07:0313976 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
13977
13978 MockWrite http_write[] = {
13979 MockWrite("GET / HTTP/1.1\r\n"
13980 "Host: www.a.com\r\n"
13981 "Connection: keep-alive\r\n\r\n"),
13982 };
13983
13984 MockRead http_read[] = {
13985 MockRead("HTTP/1.1 200 OK\r\n"),
13986 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
13987 MockRead("Content-Length: 6\r\n\r\n"),
13988 MockRead("hello!"),
13989 };
13990 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
13991 http_write, arraysize(http_write));
13992 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13993
13994 HostPortPair host_port_pair_a("www.a.com", 443);
[email protected]e6d017652013-05-17 18:01:4013995 SpdySessionKey spdy_session_key_a(
[email protected]314b03992014-04-01 01:28:5313996 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0313997 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613998 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313999
14000 TestCompletionCallback callback;
14001 HttpRequestInfo request1;
14002 request1.method = "GET";
14003 request1.url = GURL("https://www.a.com/");
14004 request1.load_flags = 0;
14005 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5014006 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0314007
14008 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
14009 EXPECT_EQ(ERR_IO_PENDING, rv);
14010 EXPECT_EQ(OK, callback.WaitForResult());
14011
14012 const HttpResponseInfo* response = trans->GetResponseInfo();
14013 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5014014 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0214015 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0314016 EXPECT_TRUE(response->was_fetched_via_spdy);
14017 EXPECT_TRUE(response->was_npn_negotiated);
14018
14019 std::string response_data;
14020 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
14021 EXPECT_EQ("hello!", response_data);
14022 trans.reset();
14023 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2614024 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314025
14026 HostPortPair host_port_pair_b("www.b.com", 443);
[email protected]e6d017652013-05-17 18:01:4014027 SpdySessionKey spdy_session_key_b(
[email protected]314b03992014-04-01 01:28:5314028 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0314029 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614030 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0314031 HttpRequestInfo request2;
14032 request2.method = "GET";
14033 request2.url = GURL("https://www.b.com/");
14034 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5014035 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0314036
14037 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
14038 EXPECT_EQ(ERR_IO_PENDING, rv);
14039 EXPECT_EQ(OK, callback.WaitForResult());
14040
14041 response = trans->GetResponseInfo();
14042 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5014043 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0214044 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0314045 EXPECT_TRUE(response->was_fetched_via_spdy);
14046 EXPECT_TRUE(response->was_npn_negotiated);
14047 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
14048 EXPECT_EQ("hello!", response_data);
14049 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614050 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314051 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2614052 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0314053
14054 HostPortPair host_port_pair_a1("www.a.com", 80);
[email protected]e6d017652013-05-17 18:01:4014055 SpdySessionKey spdy_session_key_a1(
[email protected]314b03992014-04-01 01:28:5314056 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0314057 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614058 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0314059 HttpRequestInfo request3;
14060 request3.method = "GET";
14061 request3.url = GURL("http://www.a.com/");
14062 request3.load_flags = 0;
[email protected]90499482013-06-01 00:39:5014063 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0314064
14065 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
14066 EXPECT_EQ(ERR_IO_PENDING, rv);
14067 EXPECT_EQ(OK, callback.WaitForResult());
14068
14069 response = trans->GetResponseInfo();
14070 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5014071 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]483fa202013-05-14 01:07:0314072 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14073 EXPECT_FALSE(response->was_fetched_via_spdy);
14074 EXPECT_FALSE(response->was_npn_negotiated);
14075 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
14076 EXPECT_EQ("hello!", response_data);
14077 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614078 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314079 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614080 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0314081}
14082
[email protected]79e1fd62013-06-20 06:50:0414083TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
14084 HttpRequestInfo request;
14085 request.method = "GET";
bncce36dca22015-04-21 22:11:2314086 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414087 request.load_flags = 0;
14088
mmenkee65e7af2015-10-13 17:16:4214089 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414090 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114091 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414092
ttuttled9dbc652015-09-29 20:00:5914093 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0414094 StaticSocketDataProvider data;
14095 data.set_connect_data(mock_connect);
14096 session_deps_.socket_factory->AddSocketDataProvider(&data);
14097
14098 TestCompletionCallback callback;
14099
14100 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14101 EXPECT_EQ(ERR_IO_PENDING, rv);
14102
14103 rv = callback.WaitForResult();
ttuttled9dbc652015-09-29 20:00:5914104 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
[email protected]79e1fd62013-06-20 06:50:0414105
[email protected]79e1fd62013-06-20 06:50:0414106 // We don't care whether this succeeds or fails, but it shouldn't crash.
14107 HttpRequestHeaders request_headers;
14108 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4714109
14110 ConnectionAttempts attempts;
14111 trans->GetConnectionAttempts(&attempts);
14112 ASSERT_EQ(1u, attempts.size());
ttuttled9dbc652015-09-29 20:00:5914113 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
14114
14115 IPEndPoint endpoint;
14116 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
14117 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0414118}
14119
14120TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
14121 HttpRequestInfo request;
14122 request.method = "GET";
bncce36dca22015-04-21 22:11:2314123 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414124 request.load_flags = 0;
14125
mmenkee65e7af2015-10-13 17:16:4214126 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414127 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114128 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414129
ttuttled9dbc652015-09-29 20:00:5914130 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0414131 StaticSocketDataProvider data;
14132 data.set_connect_data(mock_connect);
14133 session_deps_.socket_factory->AddSocketDataProvider(&data);
14134
14135 TestCompletionCallback callback;
14136
14137 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14138 EXPECT_EQ(ERR_IO_PENDING, rv);
14139
14140 rv = callback.WaitForResult();
ttuttled9dbc652015-09-29 20:00:5914141 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
[email protected]79e1fd62013-06-20 06:50:0414142
[email protected]79e1fd62013-06-20 06:50:0414143 // We don't care whether this succeeds or fails, but it shouldn't crash.
14144 HttpRequestHeaders request_headers;
14145 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4714146
14147 ConnectionAttempts attempts;
14148 trans->GetConnectionAttempts(&attempts);
14149 ASSERT_EQ(1u, attempts.size());
ttuttled9dbc652015-09-29 20:00:5914150 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
14151
14152 IPEndPoint endpoint;
14153 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
14154 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0414155}
14156
14157TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
14158 HttpRequestInfo request;
14159 request.method = "GET";
bncce36dca22015-04-21 22:11:2314160 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414161 request.load_flags = 0;
14162
mmenkee65e7af2015-10-13 17:16:4214163 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414164 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114165 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414166
14167 MockWrite data_writes[] = {
14168 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14169 };
14170 MockRead data_reads[] = {
14171 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
14172 };
14173
14174 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14175 data_writes, arraysize(data_writes));
14176 session_deps_.socket_factory->AddSocketDataProvider(&data);
14177
14178 TestCompletionCallback callback;
14179
14180 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14181 EXPECT_EQ(ERR_IO_PENDING, rv);
14182
14183 rv = callback.WaitForResult();
14184 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14185
[email protected]79e1fd62013-06-20 06:50:0414186 HttpRequestHeaders request_headers;
14187 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14188 EXPECT_TRUE(request_headers.HasHeader("Host"));
14189}
14190
14191TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
14192 HttpRequestInfo request;
14193 request.method = "GET";
bncce36dca22015-04-21 22:11:2314194 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414195 request.load_flags = 0;
14196
mmenkee65e7af2015-10-13 17:16:4214197 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414198 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114199 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414200
14201 MockWrite data_writes[] = {
14202 MockWrite(ASYNC, ERR_CONNECTION_RESET),
14203 };
14204 MockRead data_reads[] = {
14205 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
14206 };
14207
14208 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14209 data_writes, arraysize(data_writes));
14210 session_deps_.socket_factory->AddSocketDataProvider(&data);
14211
14212 TestCompletionCallback callback;
14213
14214 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14215 EXPECT_EQ(ERR_IO_PENDING, rv);
14216
14217 rv = callback.WaitForResult();
14218 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14219
[email protected]79e1fd62013-06-20 06:50:0414220 HttpRequestHeaders request_headers;
14221 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14222 EXPECT_TRUE(request_headers.HasHeader("Host"));
14223}
14224
14225TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
14226 HttpRequestInfo request;
14227 request.method = "GET";
bncce36dca22015-04-21 22:11:2314228 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414229 request.load_flags = 0;
14230
mmenkee65e7af2015-10-13 17:16:4214231 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414232 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114233 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414234
14235 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314236 MockWrite(
14237 "GET / HTTP/1.1\r\n"
14238 "Host: www.example.org\r\n"
14239 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414240 };
14241 MockRead data_reads[] = {
14242 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
14243 };
14244
14245 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14246 data_writes, arraysize(data_writes));
14247 session_deps_.socket_factory->AddSocketDataProvider(&data);
14248
14249 TestCompletionCallback callback;
14250
14251 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14252 EXPECT_EQ(ERR_IO_PENDING, rv);
14253
14254 rv = callback.WaitForResult();
14255 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14256
[email protected]79e1fd62013-06-20 06:50:0414257 HttpRequestHeaders request_headers;
14258 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14259 EXPECT_TRUE(request_headers.HasHeader("Host"));
14260}
14261
14262TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
14263 HttpRequestInfo request;
14264 request.method = "GET";
bncce36dca22015-04-21 22:11:2314265 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414266 request.load_flags = 0;
14267
mmenkee65e7af2015-10-13 17:16:4214268 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414269 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114270 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414271
14272 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314273 MockWrite(
14274 "GET / HTTP/1.1\r\n"
14275 "Host: www.example.org\r\n"
14276 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414277 };
14278 MockRead data_reads[] = {
14279 MockRead(ASYNC, ERR_CONNECTION_RESET),
14280 };
14281
14282 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14283 data_writes, arraysize(data_writes));
14284 session_deps_.socket_factory->AddSocketDataProvider(&data);
14285
14286 TestCompletionCallback callback;
14287
14288 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14289 EXPECT_EQ(ERR_IO_PENDING, rv);
14290
14291 rv = callback.WaitForResult();
14292 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14293
[email protected]79e1fd62013-06-20 06:50:0414294 HttpRequestHeaders request_headers;
14295 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14296 EXPECT_TRUE(request_headers.HasHeader("Host"));
14297}
14298
14299TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
14300 HttpRequestInfo request;
14301 request.method = "GET";
bncce36dca22015-04-21 22:11:2314302 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414303 request.load_flags = 0;
14304 request.extra_headers.SetHeader("X-Foo", "bar");
14305
mmenkee65e7af2015-10-13 17:16:4214306 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414307 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114308 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414309
14310 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314311 MockWrite(
14312 "GET / HTTP/1.1\r\n"
14313 "Host: www.example.org\r\n"
14314 "Connection: keep-alive\r\n"
14315 "X-Foo: bar\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414316 };
14317 MockRead data_reads[] = {
14318 MockRead("HTTP/1.1 200 OK\r\n"
14319 "Content-Length: 5\r\n\r\n"
14320 "hello"),
14321 MockRead(ASYNC, ERR_UNEXPECTED),
14322 };
14323
14324 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14325 data_writes, arraysize(data_writes));
14326 session_deps_.socket_factory->AddSocketDataProvider(&data);
14327
14328 TestCompletionCallback callback;
14329
14330 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14331 EXPECT_EQ(ERR_IO_PENDING, rv);
14332
14333 rv = callback.WaitForResult();
14334 EXPECT_EQ(OK, rv);
14335
14336 HttpRequestHeaders request_headers;
14337 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14338 std::string foo;
14339 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
14340 EXPECT_EQ("bar", foo);
14341}
14342
[email protected]bf828982013-08-14 18:01:4714343namespace {
14344
yhiranoa7e05bb2014-11-06 05:40:3914345// Fake HttpStream that simply records calls to SetPriority().
14346class FakeStream : public HttpStream,
[email protected]e86839fd2013-08-14 18:29:0314347 public base::SupportsWeakPtr<FakeStream> {
14348 public:
14349 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
dchengb03027d2014-10-21 12:00:2014350 ~FakeStream() override {}
[email protected]e86839fd2013-08-14 18:29:0314351
14352 RequestPriority priority() const { return priority_; }
14353
dchengb03027d2014-10-21 12:00:2014354 int InitializeStream(const HttpRequestInfo* request_info,
14355 RequestPriority priority,
14356 const BoundNetLog& net_log,
14357 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314358 return ERR_IO_PENDING;
14359 }
14360
dchengb03027d2014-10-21 12:00:2014361 int SendRequest(const HttpRequestHeaders& request_headers,
14362 HttpResponseInfo* response,
14363 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314364 ADD_FAILURE();
14365 return ERR_UNEXPECTED;
14366 }
14367
dchengb03027d2014-10-21 12:00:2014368 int ReadResponseHeaders(const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314369 ADD_FAILURE();
14370 return ERR_UNEXPECTED;
14371 }
14372
dchengb03027d2014-10-21 12:00:2014373 int ReadResponseBody(IOBuffer* buf,
14374 int buf_len,
14375 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314376 ADD_FAILURE();
14377 return ERR_UNEXPECTED;
14378 }
14379
dchengb03027d2014-10-21 12:00:2014380 void Close(bool not_reusable) override {}
[email protected]e86839fd2013-08-14 18:29:0314381
dchengb03027d2014-10-21 12:00:2014382 bool IsResponseBodyComplete() const override {
[email protected]e86839fd2013-08-14 18:29:0314383 ADD_FAILURE();
14384 return false;
14385 }
14386
dchengb03027d2014-10-21 12:00:2014387 bool IsConnectionReused() const override {
[email protected]e86839fd2013-08-14 18:29:0314388 ADD_FAILURE();
14389 return false;
14390 }
14391
dchengb03027d2014-10-21 12:00:2014392 void SetConnectionReused() override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0314393
mmenkebd84c392015-09-02 14:12:3414394 bool CanReuseConnection() const override { return false; }
[email protected]e86839fd2013-08-14 18:29:0314395
sclittle4de1bab92015-09-22 21:28:2414396 int64_t GetTotalReceivedBytes() const override {
[email protected]bc92bc972013-12-13 08:32:5914397 ADD_FAILURE();
14398 return 0;
14399 }
14400
sclittlebe1ccf62015-09-02 19:40:3614401 int64_t GetTotalSentBytes() const override {
14402 ADD_FAILURE();
14403 return 0;
14404 }
14405
dchengb03027d2014-10-21 12:00:2014406 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
[email protected]e86839fd2013-08-14 18:29:0314407 ADD_FAILURE();
14408 return false;
14409 }
14410
dchengb03027d2014-10-21 12:00:2014411 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
14412
14413 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
[email protected]e86839fd2013-08-14 18:29:0314414 ADD_FAILURE();
14415 }
14416
ttuttled9dbc652015-09-29 20:00:5914417 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
14418
nharperb7441ef2016-01-25 23:54:1414419 Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
14420 std::vector<uint8_t>* out) override {
14421 ADD_FAILURE();
14422 return ERR_NOT_IMPLEMENTED;
14423 }
14424
dchengb03027d2014-10-21 12:00:2014425 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0314426
zhongyica364fbb2015-12-12 03:39:1214427 void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
14428
dchengb03027d2014-10-21 12:00:2014429 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]e86839fd2013-08-14 18:29:0314430
yhiranoa7e05bb2014-11-06 05:40:3914431 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
14432
14433 HttpStream* RenewStreamForAuth() override { return NULL; }
14434
[email protected]e86839fd2013-08-14 18:29:0314435 private:
14436 RequestPriority priority_;
14437
14438 DISALLOW_COPY_AND_ASSIGN(FakeStream);
14439};
14440
14441// Fake HttpStreamRequest that simply records calls to SetPriority()
14442// and vends FakeStreams with its current priority.
[email protected]bf828982013-08-14 18:01:4714443class FakeStreamRequest : public HttpStreamRequest,
14444 public base::SupportsWeakPtr<FakeStreamRequest> {
14445 public:
[email protected]e86839fd2013-08-14 18:29:0314446 FakeStreamRequest(RequestPriority priority,
14447 HttpStreamRequest::Delegate* delegate)
14448 : priority_(priority),
[email protected]831e4a32013-11-14 02:14:4414449 delegate_(delegate),
14450 websocket_stream_create_helper_(NULL) {}
14451
14452 FakeStreamRequest(RequestPriority priority,
14453 HttpStreamRequest::Delegate* delegate,
14454 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
14455 : priority_(priority),
14456 delegate_(delegate),
14457 websocket_stream_create_helper_(create_helper) {}
[email protected]e86839fd2013-08-14 18:29:0314458
dchengb03027d2014-10-21 12:00:2014459 ~FakeStreamRequest() override {}
[email protected]bf828982013-08-14 18:01:4714460
14461 RequestPriority priority() const { return priority_; }
14462
[email protected]831e4a32013-11-14 02:14:4414463 const WebSocketHandshakeStreamBase::CreateHelper*
14464 websocket_stream_create_helper() const {
14465 return websocket_stream_create_helper_;
14466 }
14467
[email protected]e86839fd2013-08-14 18:29:0314468 // Create a new FakeStream and pass it to the request's
14469 // delegate. Returns a weak pointer to the FakeStream.
14470 base::WeakPtr<FakeStream> FinishStreamRequest() {
14471 FakeStream* fake_stream = new FakeStream(priority_);
14472 // Do this before calling OnStreamReady() as OnStreamReady() may
14473 // immediately delete |fake_stream|.
14474 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
14475 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
14476 return weak_stream;
14477 }
14478
dchengb03027d2014-10-21 12:00:2014479 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
[email protected]bf828982013-08-14 18:01:4714480 ADD_FAILURE();
14481 return ERR_UNEXPECTED;
14482 }
14483
dchengb03027d2014-10-21 12:00:2014484 LoadState GetLoadState() const override {
[email protected]bf828982013-08-14 18:01:4714485 ADD_FAILURE();
14486 return LoadState();
14487 }
14488
dchengb03027d2014-10-21 12:00:2014489 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]bf828982013-08-14 18:01:4714490
dchengb03027d2014-10-21 12:00:2014491 bool was_npn_negotiated() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714492
dchengb03027d2014-10-21 12:00:2014493 NextProto protocol_negotiated() const override { return kProtoUnknown; }
[email protected]bf828982013-08-14 18:01:4714494
dchengb03027d2014-10-21 12:00:2014495 bool using_spdy() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714496
ttuttle1f2d7e92015-04-28 16:17:4714497 const ConnectionAttempts& connection_attempts() const override {
14498 static ConnectionAttempts no_attempts;
14499 return no_attempts;
14500 }
14501
[email protected]bf828982013-08-14 18:01:4714502 private:
14503 RequestPriority priority_;
[email protected]e86839fd2013-08-14 18:29:0314504 HttpStreamRequest::Delegate* const delegate_;
[email protected]831e4a32013-11-14 02:14:4414505 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
[email protected]bf828982013-08-14 18:01:4714506
14507 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
14508};
14509
14510// Fake HttpStreamFactory that vends FakeStreamRequests.
14511class FakeStreamFactory : public HttpStreamFactory {
14512 public:
14513 FakeStreamFactory() {}
dchengb03027d2014-10-21 12:00:2014514 ~FakeStreamFactory() override {}
[email protected]bf828982013-08-14 18:01:4714515
14516 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
14517 // RequestStream() (which may be NULL if it was destroyed already).
14518 base::WeakPtr<FakeStreamRequest> last_stream_request() {
14519 return last_stream_request_;
14520 }
14521
dchengb03027d2014-10-21 12:00:2014522 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
14523 RequestPriority priority,
14524 const SSLConfig& server_ssl_config,
14525 const SSLConfig& proxy_ssl_config,
14526 HttpStreamRequest::Delegate* delegate,
14527 const BoundNetLog& net_log) override {
[email protected]e86839fd2013-08-14 18:29:0314528 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
[email protected]bf828982013-08-14 18:01:4714529 last_stream_request_ = fake_request->AsWeakPtr();
14530 return fake_request;
14531 }
14532
xunjieli11834f02015-12-22 04:27:0814533 HttpStreamRequest* RequestBidirectionalStreamJob(
14534 const HttpRequestInfo& info,
14535 RequestPriority priority,
14536 const SSLConfig& server_ssl_config,
14537 const SSLConfig& proxy_ssl_config,
14538 HttpStreamRequest::Delegate* delegate,
14539 const BoundNetLog& net_log) override {
14540 NOTREACHED();
14541 return nullptr;
14542 }
14543
dchengb03027d2014-10-21 12:00:2014544 HttpStreamRequest* RequestWebSocketHandshakeStream(
[email protected]bf828982013-08-14 18:01:4714545 const HttpRequestInfo& info,
14546 RequestPriority priority,
14547 const SSLConfig& server_ssl_config,
14548 const SSLConfig& proxy_ssl_config,
14549 HttpStreamRequest::Delegate* delegate,
[email protected]467086b2013-11-12 08:19:4614550 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
mostynbba063d6032014-10-09 11:01:1314551 const BoundNetLog& net_log) override {
[email protected]831e4a32013-11-14 02:14:4414552 FakeStreamRequest* fake_request =
14553 new FakeStreamRequest(priority, delegate, create_helper);
14554 last_stream_request_ = fake_request->AsWeakPtr();
14555 return fake_request;
[email protected]bf828982013-08-14 18:01:4714556 }
14557
dchengb03027d2014-10-21 12:00:2014558 void PreconnectStreams(int num_streams,
14559 const HttpRequestInfo& info,
dchengb03027d2014-10-21 12:00:2014560 const SSLConfig& server_ssl_config,
14561 const SSLConfig& proxy_ssl_config) override {
[email protected]bf828982013-08-14 18:01:4714562 ADD_FAILURE();
14563 }
14564
dchengb03027d2014-10-21 12:00:2014565 const HostMappingRules* GetHostMappingRules() const override {
[email protected]bf828982013-08-14 18:01:4714566 ADD_FAILURE();
14567 return NULL;
14568 }
14569
14570 private:
14571 base::WeakPtr<FakeStreamRequest> last_stream_request_;
14572
14573 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
14574};
14575
Adam Rice425cf122015-01-19 06:18:2414576// TODO(ricea): Maybe unify this with the one in
14577// url_request_http_job_unittest.cc ?
14578class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
14579 public:
14580 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection,
14581 bool using_proxy)
14582 : state_(connection.release(), using_proxy) {}
14583
14584 // Fake implementation of HttpStreamBase methods.
14585 // This ends up being quite "real" because this object has to really send data
14586 // on the mock socket. It might be easier to use the real implementation, but
14587 // the fact that the WebSocket code is not compiled on iOS makes that
14588 // difficult.
14589 int InitializeStream(const HttpRequestInfo* request_info,
14590 RequestPriority priority,
14591 const BoundNetLog& net_log,
14592 const CompletionCallback& callback) override {
14593 state_.Initialize(request_info, priority, net_log, callback);
14594 return OK;
14595 }
14596
14597 int SendRequest(const HttpRequestHeaders& request_headers,
14598 HttpResponseInfo* response,
14599 const CompletionCallback& callback) override {
14600 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
14601 response, callback);
14602 }
14603
14604 int ReadResponseHeaders(const CompletionCallback& callback) override {
14605 return parser()->ReadResponseHeaders(callback);
14606 }
14607
14608 int ReadResponseBody(IOBuffer* buf,
14609 int buf_len,
14610 const CompletionCallback& callback) override {
14611 NOTREACHED();
14612 return ERR_IO_PENDING;
14613 }
14614
14615 void Close(bool not_reusable) override {
14616 if (parser())
14617 parser()->Close(true);
14618 }
14619
14620 bool IsResponseBodyComplete() const override {
14621 NOTREACHED();
14622 return false;
14623 }
14624
Adam Rice425cf122015-01-19 06:18:2414625 bool IsConnectionReused() const override {
14626 NOTREACHED();
14627 return false;
14628 }
14629 void SetConnectionReused() override { NOTREACHED(); }
14630
mmenkebd84c392015-09-02 14:12:3414631 bool CanReuseConnection() const override { return false; }
Adam Rice425cf122015-01-19 06:18:2414632
sclittle4de1bab92015-09-22 21:28:2414633 int64_t GetTotalReceivedBytes() const override {
Adam Rice425cf122015-01-19 06:18:2414634 NOTREACHED();
14635 return 0;
14636 }
14637
sclittlebe1ccf62015-09-02 19:40:3614638 int64_t GetTotalSentBytes() const override {
14639 NOTREACHED();
14640 return 0;
14641 }
14642
Adam Rice425cf122015-01-19 06:18:2414643 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
14644 NOTREACHED();
14645 return false;
14646 }
14647
Adam Ricecb76ac62015-02-20 05:33:2514648 void GetSSLInfo(SSLInfo* ssl_info) override {}
Adam Rice425cf122015-01-19 06:18:2414649
14650 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
14651 NOTREACHED();
14652 }
14653
ttuttled9dbc652015-09-29 20:00:5914654 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
14655
nharperb7441ef2016-01-25 23:54:1414656 Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
14657 std::vector<uint8_t>* out) override {
14658 ADD_FAILURE();
14659 return ERR_NOT_IMPLEMENTED;
14660 }
14661
Adam Rice425cf122015-01-19 06:18:2414662 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
14663
zhongyica364fbb2015-12-12 03:39:1214664 void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
14665
Adam Rice425cf122015-01-19 06:18:2414666 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
14667
14668 UploadProgress GetUploadProgress() const override {
14669 NOTREACHED();
14670 return UploadProgress();
14671 }
14672
14673 HttpStream* RenewStreamForAuth() override {
14674 NOTREACHED();
14675 return nullptr;
14676 }
14677
14678 // Fake implementation of WebSocketHandshakeStreamBase method(s)
14679 scoped_ptr<WebSocketStream> Upgrade() override {
14680 NOTREACHED();
14681 return scoped_ptr<WebSocketStream>();
14682 }
14683
14684 private:
14685 HttpStreamParser* parser() const { return state_.parser(); }
14686 HttpBasicState state_;
14687
14688 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
14689};
14690
[email protected]831e4a32013-11-14 02:14:4414691// TODO(yhirano): Split this class out into a net/websockets file, if it is
14692// worth doing.
14693class FakeWebSocketStreamCreateHelper :
14694 public WebSocketHandshakeStreamBase::CreateHelper {
14695 public:
dchengb03027d2014-10-21 12:00:2014696 WebSocketHandshakeStreamBase* CreateBasicStream(
[email protected]7e841a52013-11-22 09:04:2114697 scoped_ptr<ClientSocketHandle> connection,
mostynbba063d6032014-10-09 11:01:1314698 bool using_proxy) override {
dchengc7eeda422015-12-26 03:56:4814699 return new FakeWebSocketBasicHandshakeStream(std::move(connection),
Adam Rice425cf122015-01-19 06:18:2414700 using_proxy);
[email protected]831e4a32013-11-14 02:14:4414701 }
14702
dchengb03027d2014-10-21 12:00:2014703 WebSocketHandshakeStreamBase* CreateSpdyStream(
[email protected]831e4a32013-11-14 02:14:4414704 const base::WeakPtr<SpdySession>& session,
mostynbba063d6032014-10-09 11:01:1314705 bool use_relative_url) override {
[email protected]831e4a32013-11-14 02:14:4414706 NOTREACHED();
14707 return NULL;
14708 };
14709
dchengb03027d2014-10-21 12:00:2014710 ~FakeWebSocketStreamCreateHelper() override {}
[email protected]831e4a32013-11-14 02:14:4414711
14712 virtual scoped_ptr<WebSocketStream> Upgrade() {
14713 NOTREACHED();
14714 return scoped_ptr<WebSocketStream>();
14715 }
14716};
14717
[email protected]bf828982013-08-14 18:01:4714718} // namespace
14719
14720// Make sure that HttpNetworkTransaction passes on its priority to its
14721// stream request on start.
14722TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
mmenkee65e7af2015-10-13 17:16:4214723 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14724 HttpNetworkSessionPeer peer(session.get());
[email protected]bf828982013-08-14 18:01:4714725 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414726 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714727
dcheng48459ac22014-08-26 00:46:4114728 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714729
14730 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
14731
14732 HttpRequestInfo request;
14733 TestCompletionCallback callback;
14734 EXPECT_EQ(ERR_IO_PENDING,
14735 trans.Start(&request, callback.callback(), BoundNetLog()));
14736
14737 base::WeakPtr<FakeStreamRequest> fake_request =
14738 fake_factory->last_stream_request();
14739 ASSERT_TRUE(fake_request != NULL);
14740 EXPECT_EQ(LOW, fake_request->priority());
14741}
14742
14743// Make sure that HttpNetworkTransaction passes on its priority
14744// updates to its stream request.
14745TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
mmenkee65e7af2015-10-13 17:16:4214746 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14747 HttpNetworkSessionPeer peer(session.get());
[email protected]bf828982013-08-14 18:01:4714748 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414749 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714750
dcheng48459ac22014-08-26 00:46:4114751 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714752
14753 HttpRequestInfo request;
14754 TestCompletionCallback callback;
14755 EXPECT_EQ(ERR_IO_PENDING,
14756 trans.Start(&request, callback.callback(), BoundNetLog()));
14757
14758 base::WeakPtr<FakeStreamRequest> fake_request =
14759 fake_factory->last_stream_request();
14760 ASSERT_TRUE(fake_request != NULL);
14761 EXPECT_EQ(LOW, fake_request->priority());
14762
14763 trans.SetPriority(LOWEST);
14764 ASSERT_TRUE(fake_request != NULL);
14765 EXPECT_EQ(LOWEST, fake_request->priority());
14766}
14767
[email protected]e86839fd2013-08-14 18:29:0314768// Make sure that HttpNetworkTransaction passes on its priority
14769// updates to its stream.
14770TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
mmenkee65e7af2015-10-13 17:16:4214771 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14772 HttpNetworkSessionPeer peer(session.get());
[email protected]e86839fd2013-08-14 18:29:0314773 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414774 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]e86839fd2013-08-14 18:29:0314775
dcheng48459ac22014-08-26 00:46:4114776 HttpNetworkTransaction trans(LOW, session.get());
[email protected]e86839fd2013-08-14 18:29:0314777
14778 HttpRequestInfo request;
14779 TestCompletionCallback callback;
14780 EXPECT_EQ(ERR_IO_PENDING,
14781 trans.Start(&request, callback.callback(), BoundNetLog()));
14782
14783 base::WeakPtr<FakeStreamRequest> fake_request =
14784 fake_factory->last_stream_request();
14785 ASSERT_TRUE(fake_request != NULL);
14786 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
14787 ASSERT_TRUE(fake_stream != NULL);
14788 EXPECT_EQ(LOW, fake_stream->priority());
14789
14790 trans.SetPriority(LOWEST);
14791 EXPECT_EQ(LOWEST, fake_stream->priority());
14792}
14793
[email protected]831e4a32013-11-14 02:14:4414794TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
14795 // The same logic needs to be tested for both ws: and wss: schemes, but this
14796 // test is already parameterised on NextProto, so it uses a loop to verify
14797 // that the different schemes work.
bncce36dca22015-04-21 22:11:2314798 std::string test_cases[] = {"ws://www.example.org/",
14799 "wss://www.example.org/"};
[email protected]831e4a32013-11-14 02:14:4414800 for (size_t i = 0; i < arraysize(test_cases); ++i) {
mmenkee65e7af2015-10-13 17:16:4214801 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14802 HttpNetworkSessionPeer peer(session.get());
[email protected]831e4a32013-11-14 02:14:4414803 FakeStreamFactory* fake_factory = new FakeStreamFactory();
14804 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
[email protected]0191b51c2013-11-18 10:55:2314805 peer.SetHttpStreamFactoryForWebSocket(
[email protected]831e4a32013-11-14 02:14:4414806 scoped_ptr<HttpStreamFactory>(fake_factory));
14807
dcheng48459ac22014-08-26 00:46:4114808 HttpNetworkTransaction trans(LOW, session.get());
[email protected]831e4a32013-11-14 02:14:4414809 trans.SetWebSocketHandshakeStreamCreateHelper(
14810 &websocket_stream_create_helper);
14811
14812 HttpRequestInfo request;
14813 TestCompletionCallback callback;
14814 request.method = "GET";
14815 request.url = GURL(test_cases[i]);
14816
14817 EXPECT_EQ(ERR_IO_PENDING,
14818 trans.Start(&request, callback.callback(), BoundNetLog()));
14819
14820 base::WeakPtr<FakeStreamRequest> fake_request =
14821 fake_factory->last_stream_request();
14822 ASSERT_TRUE(fake_request != NULL);
14823 EXPECT_EQ(&websocket_stream_create_helper,
14824 fake_request->websocket_stream_create_helper());
14825 }
14826}
14827
[email protected]043b68c82013-08-22 23:41:5214828// Tests that when a used socket is returned to the SSL socket pool, it's closed
14829// if the transport socket pool is stalled on the global socket limit.
14830TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
14831 ClientSocketPoolManager::set_max_sockets_per_group(
14832 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14833 ClientSocketPoolManager::set_max_sockets_per_pool(
14834 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14835
14836 // Set up SSL request.
14837
14838 HttpRequestInfo ssl_request;
14839 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2314840 ssl_request.url = GURL("https://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214841
14842 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2314843 MockWrite(
14844 "GET / HTTP/1.1\r\n"
14845 "Host: www.example.org\r\n"
14846 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214847 };
14848 MockRead ssl_reads[] = {
14849 MockRead("HTTP/1.1 200 OK\r\n"),
14850 MockRead("Content-Length: 11\r\n\r\n"),
14851 MockRead("hello world"),
14852 MockRead(SYNCHRONOUS, OK),
14853 };
14854 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
14855 ssl_writes, arraysize(ssl_writes));
14856 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
14857
14858 SSLSocketDataProvider ssl(ASYNC, OK);
14859 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14860
14861 // Set up HTTP request.
14862
14863 HttpRequestInfo http_request;
14864 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2314865 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214866
14867 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2314868 MockWrite(
14869 "GET / HTTP/1.1\r\n"
14870 "Host: www.example.org\r\n"
14871 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214872 };
14873 MockRead http_reads[] = {
14874 MockRead("HTTP/1.1 200 OK\r\n"),
14875 MockRead("Content-Length: 7\r\n\r\n"),
14876 MockRead("falafel"),
14877 MockRead(SYNCHRONOUS, OK),
14878 };
14879 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
14880 http_writes, arraysize(http_writes));
14881 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14882
mmenkee65e7af2015-10-13 17:16:4214883 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5214884
14885 // Start the SSL request.
14886 TestCompletionCallback ssl_callback;
14887 scoped_ptr<HttpTransaction> ssl_trans(
14888 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14889 ASSERT_EQ(ERR_IO_PENDING,
14890 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
14891 BoundNetLog()));
14892
14893 // Start the HTTP request. Pool should stall.
14894 TestCompletionCallback http_callback;
14895 scoped_ptr<HttpTransaction> http_trans(
14896 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14897 ASSERT_EQ(ERR_IO_PENDING,
14898 http_trans->Start(&http_request, http_callback.callback(),
14899 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4114900 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214901
14902 // Wait for response from SSL request.
14903 ASSERT_EQ(OK, ssl_callback.WaitForResult());
14904 std::string response_data;
14905 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
14906 EXPECT_EQ("hello world", response_data);
14907
14908 // The SSL socket should automatically be closed, so the HTTP request can
14909 // start.
dcheng48459ac22014-08-26 00:46:4114910 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
14911 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214912
14913 // The HTTP request can now complete.
14914 ASSERT_EQ(OK, http_callback.WaitForResult());
14915 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
14916 EXPECT_EQ("falafel", response_data);
14917
dcheng48459ac22014-08-26 00:46:4114918 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214919}
14920
14921// Tests that when a SSL connection is established but there's no corresponding
14922// request that needs it, the new socket is closed if the transport socket pool
14923// is stalled on the global socket limit.
14924TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
14925 ClientSocketPoolManager::set_max_sockets_per_group(
14926 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14927 ClientSocketPoolManager::set_max_sockets_per_pool(
14928 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14929
14930 // Set up an ssl request.
14931
14932 HttpRequestInfo ssl_request;
14933 ssl_request.method = "GET";
14934 ssl_request.url = GURL("https://www.foopy.com/");
14935
14936 // No data will be sent on the SSL socket.
14937 StaticSocketDataProvider ssl_data;
14938 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
14939
14940 SSLSocketDataProvider ssl(ASYNC, OK);
14941 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14942
14943 // Set up HTTP request.
14944
14945 HttpRequestInfo http_request;
14946 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2314947 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214948
14949 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2314950 MockWrite(
14951 "GET / HTTP/1.1\r\n"
14952 "Host: www.example.org\r\n"
14953 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214954 };
14955 MockRead http_reads[] = {
14956 MockRead("HTTP/1.1 200 OK\r\n"),
14957 MockRead("Content-Length: 7\r\n\r\n"),
14958 MockRead("falafel"),
14959 MockRead(SYNCHRONOUS, OK),
14960 };
14961 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
14962 http_writes, arraysize(http_writes));
14963 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14964
mmenkee65e7af2015-10-13 17:16:4214965 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5214966
14967 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
14968 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2914969 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
14970 SSLConfig ssl_config;
[email protected]043b68c82013-08-22 23:41:5214971 session->ssl_config_service()->GetSSLConfig(&ssl_config);
mmenked1205bd2015-07-15 22:26:3514972 http_stream_factory->PreconnectStreams(1, ssl_request, ssl_config,
14973 ssl_config);
dcheng48459ac22014-08-26 00:46:4114974 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214975
14976 // Start the HTTP request. Pool should stall.
14977 TestCompletionCallback http_callback;
14978 scoped_ptr<HttpTransaction> http_trans(
14979 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14980 ASSERT_EQ(ERR_IO_PENDING,
14981 http_trans->Start(&http_request, http_callback.callback(),
14982 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4114983 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214984
14985 // The SSL connection will automatically be closed once the connection is
14986 // established, to let the HTTP request start.
14987 ASSERT_EQ(OK, http_callback.WaitForResult());
14988 std::string response_data;
14989 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
14990 EXPECT_EQ("falafel", response_data);
14991
dcheng48459ac22014-08-26 00:46:4114992 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214993}
14994
[email protected]02d74a02014-04-23 18:10:5414995TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2214996 std::vector<scoped_ptr<UploadElementReader>> element_readers;
14997 element_readers.push_back(
14998 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
14999 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415000
15001 HttpRequestInfo request;
15002 request.method = "POST";
15003 request.url = GURL("http://www.foo.com/");
15004 request.upload_data_stream = &upload_data_stream;
15005 request.load_flags = 0;
15006
mmenkee65e7af2015-10-13 17:16:4215007 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415008 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115009 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415010 // Send headers successfully, but get an error while sending the body.
15011 MockWrite data_writes[] = {
15012 MockWrite("POST / HTTP/1.1\r\n"
15013 "Host: www.foo.com\r\n"
15014 "Connection: keep-alive\r\n"
15015 "Content-Length: 3\r\n\r\n"),
15016 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15017 };
15018
15019 MockRead data_reads[] = {
15020 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15021 MockRead("hello world"),
15022 MockRead(SYNCHRONOUS, OK),
15023 };
15024 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15025 arraysize(data_writes));
15026 session_deps_.socket_factory->AddSocketDataProvider(&data);
15027
15028 TestCompletionCallback callback;
15029
15030 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15031 EXPECT_EQ(ERR_IO_PENDING, rv);
15032
15033 rv = callback.WaitForResult();
15034 EXPECT_EQ(OK, rv);
15035
15036 const HttpResponseInfo* response = trans->GetResponseInfo();
15037 ASSERT_TRUE(response != NULL);
15038
15039 EXPECT_TRUE(response->headers.get() != NULL);
15040 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15041
15042 std::string response_data;
15043 rv = ReadTransaction(trans.get(), &response_data);
15044 EXPECT_EQ(OK, rv);
15045 EXPECT_EQ("hello world", response_data);
15046}
15047
15048// This test makes sure the retry logic doesn't trigger when reading an error
15049// response from a server that rejected a POST with a CONNECTION_RESET.
15050TEST_P(HttpNetworkTransactionTest,
15051 PostReadsErrorResponseAfterResetOnReusedSocket) {
mmenkee65e7af2015-10-13 17:16:4215052 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415053 MockWrite data_writes[] = {
15054 MockWrite("GET / HTTP/1.1\r\n"
15055 "Host: www.foo.com\r\n"
15056 "Connection: keep-alive\r\n\r\n"),
15057 MockWrite("POST / HTTP/1.1\r\n"
15058 "Host: www.foo.com\r\n"
15059 "Connection: keep-alive\r\n"
15060 "Content-Length: 3\r\n\r\n"),
15061 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15062 };
15063
15064 MockRead data_reads[] = {
15065 MockRead("HTTP/1.1 200 Peachy\r\n"
15066 "Content-Length: 14\r\n\r\n"),
15067 MockRead("first response"),
15068 MockRead("HTTP/1.1 400 Not OK\r\n"
15069 "Content-Length: 15\r\n\r\n"),
15070 MockRead("second response"),
15071 MockRead(SYNCHRONOUS, OK),
15072 };
15073 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15074 arraysize(data_writes));
15075 session_deps_.socket_factory->AddSocketDataProvider(&data);
15076
15077 TestCompletionCallback callback;
15078 HttpRequestInfo request1;
15079 request1.method = "GET";
15080 request1.url = GURL("http://www.foo.com/");
15081 request1.load_flags = 0;
15082
15083 scoped_ptr<HttpTransaction> trans1(
dcheng48459ac22014-08-26 00:46:4115084 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415085 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
15086 EXPECT_EQ(ERR_IO_PENDING, rv);
15087
15088 rv = callback.WaitForResult();
15089 EXPECT_EQ(OK, rv);
15090
15091 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
15092 ASSERT_TRUE(response1 != NULL);
15093
15094 EXPECT_TRUE(response1->headers.get() != NULL);
15095 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
15096
15097 std::string response_data1;
15098 rv = ReadTransaction(trans1.get(), &response_data1);
15099 EXPECT_EQ(OK, rv);
15100 EXPECT_EQ("first response", response_data1);
15101 // Delete the transaction to release the socket back into the socket pool.
15102 trans1.reset();
15103
olli.raula6df48b2a2015-11-26 07:40:2215104 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15105 element_readers.push_back(
15106 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15107 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415108
15109 HttpRequestInfo request2;
15110 request2.method = "POST";
15111 request2.url = GURL("http://www.foo.com/");
15112 request2.upload_data_stream = &upload_data_stream;
15113 request2.load_flags = 0;
15114
15115 scoped_ptr<HttpTransaction> trans2(
dcheng48459ac22014-08-26 00:46:4115116 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415117 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
15118 EXPECT_EQ(ERR_IO_PENDING, rv);
15119
15120 rv = callback.WaitForResult();
15121 EXPECT_EQ(OK, rv);
15122
15123 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
15124 ASSERT_TRUE(response2 != NULL);
15125
15126 EXPECT_TRUE(response2->headers.get() != NULL);
15127 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
15128
15129 std::string response_data2;
15130 rv = ReadTransaction(trans2.get(), &response_data2);
15131 EXPECT_EQ(OK, rv);
15132 EXPECT_EQ("second response", response_data2);
15133}
15134
15135TEST_P(HttpNetworkTransactionTest,
15136 PostReadsErrorResponseAfterResetPartialBodySent) {
olli.raula6df48b2a2015-11-26 07:40:2215137 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15138 element_readers.push_back(
15139 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15140 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415141
15142 HttpRequestInfo request;
15143 request.method = "POST";
15144 request.url = GURL("http://www.foo.com/");
15145 request.upload_data_stream = &upload_data_stream;
15146 request.load_flags = 0;
15147
mmenkee65e7af2015-10-13 17:16:4215148 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415149 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115150 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415151 // Send headers successfully, but get an error while sending the body.
15152 MockWrite data_writes[] = {
15153 MockWrite("POST / HTTP/1.1\r\n"
15154 "Host: www.foo.com\r\n"
15155 "Connection: keep-alive\r\n"
15156 "Content-Length: 3\r\n\r\n"
15157 "fo"),
15158 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15159 };
15160
15161 MockRead data_reads[] = {
15162 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15163 MockRead("hello world"),
15164 MockRead(SYNCHRONOUS, OK),
15165 };
15166 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15167 arraysize(data_writes));
15168 session_deps_.socket_factory->AddSocketDataProvider(&data);
15169
15170 TestCompletionCallback callback;
15171
15172 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15173 EXPECT_EQ(ERR_IO_PENDING, rv);
15174
15175 rv = callback.WaitForResult();
15176 EXPECT_EQ(OK, rv);
15177
15178 const HttpResponseInfo* response = trans->GetResponseInfo();
15179 ASSERT_TRUE(response != NULL);
15180
15181 EXPECT_TRUE(response->headers.get() != NULL);
15182 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15183
15184 std::string response_data;
15185 rv = ReadTransaction(trans.get(), &response_data);
15186 EXPECT_EQ(OK, rv);
15187 EXPECT_EQ("hello world", response_data);
15188}
15189
15190// This tests the more common case than the previous test, where headers and
15191// body are not merged into a single request.
15192TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0715193 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5415194
15195 HttpRequestInfo request;
15196 request.method = "POST";
15197 request.url = GURL("http://www.foo.com/");
15198 request.upload_data_stream = &upload_data_stream;
15199 request.load_flags = 0;
15200
mmenkee65e7af2015-10-13 17:16:4215201 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415202 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115203 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415204 // Send headers successfully, but get an error while sending the body.
15205 MockWrite data_writes[] = {
15206 MockWrite("POST / HTTP/1.1\r\n"
15207 "Host: www.foo.com\r\n"
15208 "Connection: keep-alive\r\n"
15209 "Transfer-Encoding: chunked\r\n\r\n"),
15210 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15211 };
15212
15213 MockRead data_reads[] = {
15214 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15215 MockRead("hello world"),
15216 MockRead(SYNCHRONOUS, OK),
15217 };
15218 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15219 arraysize(data_writes));
15220 session_deps_.socket_factory->AddSocketDataProvider(&data);
15221
15222 TestCompletionCallback callback;
15223
15224 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15225 EXPECT_EQ(ERR_IO_PENDING, rv);
15226 // Make sure the headers are sent before adding a chunk. This ensures that
15227 // they can't be merged with the body in a single send. Not currently
15228 // necessary since a chunked body is never merged with headers, but this makes
15229 // the test more future proof.
15230 base::RunLoop().RunUntilIdle();
15231
mmenkecbc2b712014-10-09 20:29:0715232 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5415233
15234 rv = callback.WaitForResult();
15235 EXPECT_EQ(OK, rv);
15236
15237 const HttpResponseInfo* response = trans->GetResponseInfo();
15238 ASSERT_TRUE(response != NULL);
15239
15240 EXPECT_TRUE(response->headers.get() != NULL);
15241 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15242
15243 std::string response_data;
15244 rv = ReadTransaction(trans.get(), &response_data);
15245 EXPECT_EQ(OK, rv);
15246 EXPECT_EQ("hello world", response_data);
15247}
15248
15249TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
olli.raula6df48b2a2015-11-26 07:40:2215250 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15251 element_readers.push_back(
15252 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15253 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415254
15255 HttpRequestInfo request;
15256 request.method = "POST";
15257 request.url = GURL("http://www.foo.com/");
15258 request.upload_data_stream = &upload_data_stream;
15259 request.load_flags = 0;
15260
mmenkee65e7af2015-10-13 17:16:4215261 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415262 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115263 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415264
15265 MockWrite data_writes[] = {
15266 MockWrite("POST / HTTP/1.1\r\n"
15267 "Host: www.foo.com\r\n"
15268 "Connection: keep-alive\r\n"
15269 "Content-Length: 3\r\n\r\n"),
15270 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15271 };
15272
15273 MockRead data_reads[] = {
15274 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
15275 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15276 MockRead("hello world"),
15277 MockRead(SYNCHRONOUS, OK),
15278 };
15279 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15280 arraysize(data_writes));
15281 session_deps_.socket_factory->AddSocketDataProvider(&data);
15282
15283 TestCompletionCallback callback;
15284
15285 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15286 EXPECT_EQ(ERR_IO_PENDING, rv);
15287
15288 rv = callback.WaitForResult();
15289 EXPECT_EQ(OK, rv);
15290
15291 const HttpResponseInfo* response = trans->GetResponseInfo();
15292 ASSERT_TRUE(response != NULL);
15293
15294 EXPECT_TRUE(response->headers.get() != NULL);
15295 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15296
15297 std::string response_data;
15298 rv = ReadTransaction(trans.get(), &response_data);
15299 EXPECT_EQ(OK, rv);
15300 EXPECT_EQ("hello world", response_data);
15301}
15302
15303TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215304 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15305 element_readers.push_back(
15306 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15307 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415308
15309 HttpRequestInfo request;
15310 request.method = "POST";
15311 request.url = GURL("http://www.foo.com/");
15312 request.upload_data_stream = &upload_data_stream;
15313 request.load_flags = 0;
15314
mmenkee65e7af2015-10-13 17:16:4215315 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415316 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115317 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415318 // Send headers successfully, but get an error while sending the body.
15319 MockWrite data_writes[] = {
15320 MockWrite("POST / HTTP/1.1\r\n"
15321 "Host: www.foo.com\r\n"
15322 "Connection: keep-alive\r\n"
15323 "Content-Length: 3\r\n\r\n"),
15324 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15325 };
15326
15327 MockRead data_reads[] = {
15328 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
15329 MockRead("hello world"),
15330 MockRead(SYNCHRONOUS, OK),
15331 };
15332 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15333 arraysize(data_writes));
15334 session_deps_.socket_factory->AddSocketDataProvider(&data);
15335
15336 TestCompletionCallback callback;
15337
15338 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15339 EXPECT_EQ(ERR_IO_PENDING, rv);
15340
15341 rv = callback.WaitForResult();
15342 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415343}
15344
15345TEST_P(HttpNetworkTransactionTest,
15346 PostIgnoresNonErrorResponseAfterResetAnd100) {
olli.raula6df48b2a2015-11-26 07:40:2215347 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15348 element_readers.push_back(
15349 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15350 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415351
15352 HttpRequestInfo request;
15353 request.method = "POST";
15354 request.url = GURL("http://www.foo.com/");
15355 request.upload_data_stream = &upload_data_stream;
15356 request.load_flags = 0;
15357
mmenkee65e7af2015-10-13 17:16:4215358 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415359 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115360 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415361 // Send headers successfully, but get an error while sending the body.
15362 MockWrite data_writes[] = {
15363 MockWrite("POST / HTTP/1.1\r\n"
15364 "Host: www.foo.com\r\n"
15365 "Connection: keep-alive\r\n"
15366 "Content-Length: 3\r\n\r\n"),
15367 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15368 };
15369
15370 MockRead data_reads[] = {
15371 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
15372 MockRead("HTTP/1.0 302 Redirect\r\n"),
15373 MockRead("Location: http://somewhere-else.com/\r\n"),
15374 MockRead("Content-Length: 0\r\n\r\n"),
15375 MockRead(SYNCHRONOUS, OK),
15376 };
15377 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15378 arraysize(data_writes));
15379 session_deps_.socket_factory->AddSocketDataProvider(&data);
15380
15381 TestCompletionCallback callback;
15382
15383 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15384 EXPECT_EQ(ERR_IO_PENDING, rv);
15385
15386 rv = callback.WaitForResult();
15387 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415388}
15389
15390TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215391 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15392 element_readers.push_back(
15393 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15394 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415395
15396 HttpRequestInfo request;
15397 request.method = "POST";
15398 request.url = GURL("http://www.foo.com/");
15399 request.upload_data_stream = &upload_data_stream;
15400 request.load_flags = 0;
15401
mmenkee65e7af2015-10-13 17:16:4215402 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415403 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115404 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415405 // Send headers successfully, but get an error while sending the body.
15406 MockWrite data_writes[] = {
15407 MockWrite("POST / HTTP/1.1\r\n"
15408 "Host: www.foo.com\r\n"
15409 "Connection: keep-alive\r\n"
15410 "Content-Length: 3\r\n\r\n"),
15411 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15412 };
15413
15414 MockRead data_reads[] = {
15415 MockRead("HTTP 0.9 rocks!"),
15416 MockRead(SYNCHRONOUS, OK),
15417 };
15418 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15419 arraysize(data_writes));
15420 session_deps_.socket_factory->AddSocketDataProvider(&data);
15421
15422 TestCompletionCallback callback;
15423
15424 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15425 EXPECT_EQ(ERR_IO_PENDING, rv);
15426
15427 rv = callback.WaitForResult();
15428 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415429}
15430
15431TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215432 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15433 element_readers.push_back(
15434 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15435 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415436
15437 HttpRequestInfo request;
15438 request.method = "POST";
15439 request.url = GURL("http://www.foo.com/");
15440 request.upload_data_stream = &upload_data_stream;
15441 request.load_flags = 0;
15442
mmenkee65e7af2015-10-13 17:16:4215443 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415444 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115445 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415446 // Send headers successfully, but get an error while sending the body.
15447 MockWrite data_writes[] = {
15448 MockWrite("POST / HTTP/1.1\r\n"
15449 "Host: www.foo.com\r\n"
15450 "Connection: keep-alive\r\n"
15451 "Content-Length: 3\r\n\r\n"),
15452 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15453 };
15454
15455 MockRead data_reads[] = {
15456 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
15457 MockRead(SYNCHRONOUS, OK),
15458 };
15459 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15460 arraysize(data_writes));
15461 session_deps_.socket_factory->AddSocketDataProvider(&data);
15462
15463 TestCompletionCallback callback;
15464
15465 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15466 EXPECT_EQ(ERR_IO_PENDING, rv);
15467
15468 rv = callback.WaitForResult();
15469 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415470}
15471
Adam Rice425cf122015-01-19 06:18:2415472// Verify that proxy headers are not sent to the destination server when
15473// establishing a tunnel for a secure WebSocket connection.
15474TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
15475 HttpRequestInfo request;
15476 request.method = "GET";
bncce36dca22015-04-21 22:11:2315477 request.url = GURL("wss://www.example.org/");
Adam Rice425cf122015-01-19 06:18:2415478 AddWebSocketHeaders(&request.extra_headers);
15479
15480 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:0315481 session_deps_.proxy_service =
15482 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
Adam Rice425cf122015-01-19 06:18:2415483
mmenkee65e7af2015-10-13 17:16:4215484 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2415485
15486 // Since a proxy is configured, try to establish a tunnel.
15487 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1715488 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15489 "Host: www.example.org:443\r\n"
15490 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415491
15492 // After calling trans->RestartWithAuth(), this is the request we should
15493 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1715494 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15495 "Host: www.example.org:443\r\n"
15496 "Proxy-Connection: keep-alive\r\n"
15497 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415498
rsleevidb16bb02015-11-12 23:47:1715499 MockWrite("GET / HTTP/1.1\r\n"
15500 "Host: www.example.org\r\n"
15501 "Connection: Upgrade\r\n"
15502 "Upgrade: websocket\r\n"
15503 "Origin: http://www.example.org\r\n"
15504 "Sec-WebSocket-Version: 13\r\n"
15505 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415506 };
15507
15508 // The proxy responds to the connect with a 407, using a persistent
15509 // connection.
15510 MockRead data_reads[] = {
15511 // No credentials.
15512 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
15513 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
mmenkee71e15332015-10-07 16:39:5415514 MockRead("Content-Length: 0\r\n"),
15515 MockRead("Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415516
15517 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15518
15519 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15520 MockRead("Upgrade: websocket\r\n"),
15521 MockRead("Connection: Upgrade\r\n"),
15522 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15523 };
15524
15525 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15526 arraysize(data_writes));
15527 session_deps_.socket_factory->AddSocketDataProvider(&data);
15528 SSLSocketDataProvider ssl(ASYNC, OK);
15529 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15530
15531 scoped_ptr<HttpTransaction> trans(
15532 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15533 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15534 trans->SetWebSocketHandshakeStreamCreateHelper(
15535 &websocket_stream_create_helper);
15536
15537 {
15538 TestCompletionCallback callback;
15539
15540 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15541 EXPECT_EQ(ERR_IO_PENDING, rv);
15542
15543 rv = callback.WaitForResult();
15544 EXPECT_EQ(OK, rv);
15545 }
15546
15547 const HttpResponseInfo* response = trans->GetResponseInfo();
15548 ASSERT_TRUE(response);
15549 ASSERT_TRUE(response->headers.get());
15550 EXPECT_EQ(407, response->headers->response_code());
15551
15552 {
15553 TestCompletionCallback callback;
15554
15555 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
15556 callback.callback());
15557 EXPECT_EQ(ERR_IO_PENDING, rv);
15558
15559 rv = callback.WaitForResult();
15560 EXPECT_EQ(OK, rv);
15561 }
15562
15563 response = trans->GetResponseInfo();
15564 ASSERT_TRUE(response);
15565 ASSERT_TRUE(response->headers.get());
15566
15567 EXPECT_EQ(101, response->headers->response_code());
15568
15569 trans.reset();
15570 session->CloseAllConnections();
15571}
15572
15573// Verify that proxy headers are not sent to the destination server when
15574// establishing a tunnel for an insecure WebSocket connection.
15575// This requires the authentication info to be injected into the auth cache
15576// due to crbug.com/395064
15577// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
15578TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
15579 HttpRequestInfo request;
15580 request.method = "GET";
bncce36dca22015-04-21 22:11:2315581 request.url = GURL("ws://www.example.org/");
Adam Rice425cf122015-01-19 06:18:2415582 AddWebSocketHeaders(&request.extra_headers);
15583
15584 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:0315585 session_deps_.proxy_service =
15586 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
Adam Rice425cf122015-01-19 06:18:2415587
mmenkee65e7af2015-10-13 17:16:4215588 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2415589
15590 MockWrite data_writes[] = {
15591 // Try to establish a tunnel for the WebSocket connection, with
15592 // credentials. Because WebSockets have a separate set of socket pools,
15593 // they cannot and will not use the same TCP/IP connection as the
15594 // preflight HTTP request.
15595 MockWrite(
bncce36dca22015-04-21 22:11:2315596 "CONNECT www.example.org:80 HTTP/1.1\r\n"
15597 "Host: www.example.org:80\r\n"
Adam Rice425cf122015-01-19 06:18:2415598 "Proxy-Connection: keep-alive\r\n"
15599 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
15600
15601 MockWrite(
15602 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2315603 "Host: www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415604 "Connection: Upgrade\r\n"
15605 "Upgrade: websocket\r\n"
bncce36dca22015-04-21 22:11:2315606 "Origin: http://www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415607 "Sec-WebSocket-Version: 13\r\n"
15608 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
15609 };
15610
15611 MockRead data_reads[] = {
15612 // HTTP CONNECT with credentials.
15613 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15614
15615 // WebSocket connection established inside tunnel.
15616 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15617 MockRead("Upgrade: websocket\r\n"),
15618 MockRead("Connection: Upgrade\r\n"),
15619 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15620 };
15621
15622 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15623 arraysize(data_writes));
15624 session_deps_.socket_factory->AddSocketDataProvider(&data);
15625
15626 session->http_auth_cache()->Add(
15627 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
15628 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
15629
15630 scoped_ptr<HttpTransaction> trans(
15631 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15632 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15633 trans->SetWebSocketHandshakeStreamCreateHelper(
15634 &websocket_stream_create_helper);
15635
15636 TestCompletionCallback callback;
15637
15638 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15639 EXPECT_EQ(ERR_IO_PENDING, rv);
15640
15641 rv = callback.WaitForResult();
15642 EXPECT_EQ(OK, rv);
15643
15644 const HttpResponseInfo* response = trans->GetResponseInfo();
15645 ASSERT_TRUE(response);
15646 ASSERT_TRUE(response->headers.get());
15647
15648 EXPECT_EQ(101, response->headers->response_code());
15649
15650 trans.reset();
15651 session->CloseAllConnections();
15652}
15653
sclittlefb249892015-09-10 21:33:2215654TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
olli.raula6df48b2a2015-11-26 07:40:2215655 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15656 element_readers.push_back(
15657 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15658 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2215659
15660 HttpRequestInfo request;
15661 request.method = "POST";
15662 request.url = GURL("http://www.foo.com/");
15663 request.upload_data_stream = &upload_data_stream;
15664
mmenkee65e7af2015-10-13 17:16:4215665 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215666 scoped_ptr<HttpTransaction> trans(
15667 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15668 MockWrite data_writes[] = {
15669 MockWrite("POST / HTTP/1.1\r\n"
15670 "Host: www.foo.com\r\n"
15671 "Connection: keep-alive\r\n"
15672 "Content-Length: 3\r\n\r\n"),
15673 MockWrite("foo"),
15674 };
15675
15676 MockRead data_reads[] = {
15677 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15678 MockRead(SYNCHRONOUS, OK),
15679 };
15680 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15681 arraysize(data_writes));
15682 session_deps_.socket_factory->AddSocketDataProvider(&data);
15683
15684 TestCompletionCallback callback;
15685
15686 EXPECT_EQ(ERR_IO_PENDING,
15687 trans->Start(&request, callback.callback(), BoundNetLog()));
15688 EXPECT_EQ(OK, callback.WaitForResult());
15689
15690 std::string response_data;
15691 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15692
15693 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15694 trans->GetTotalSentBytes());
15695 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15696 trans->GetTotalReceivedBytes());
15697}
15698
15699TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
olli.raula6df48b2a2015-11-26 07:40:2215700 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15701 element_readers.push_back(
15702 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15703 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2215704
15705 HttpRequestInfo request;
15706 request.method = "POST";
15707 request.url = GURL("http://www.foo.com/");
15708 request.upload_data_stream = &upload_data_stream;
15709
mmenkee65e7af2015-10-13 17:16:4215710 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215711 scoped_ptr<HttpTransaction> trans(
15712 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15713 MockWrite data_writes[] = {
15714 MockWrite("POST / HTTP/1.1\r\n"
15715 "Host: www.foo.com\r\n"
15716 "Connection: keep-alive\r\n"
15717 "Content-Length: 3\r\n\r\n"),
15718 MockWrite("foo"),
15719 };
15720
15721 MockRead data_reads[] = {
15722 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
15723 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15724 MockRead(SYNCHRONOUS, OK),
15725 };
15726 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15727 arraysize(data_writes));
15728 session_deps_.socket_factory->AddSocketDataProvider(&data);
15729
15730 TestCompletionCallback callback;
15731
15732 EXPECT_EQ(ERR_IO_PENDING,
15733 trans->Start(&request, callback.callback(), BoundNetLog()));
15734 EXPECT_EQ(OK, callback.WaitForResult());
15735
15736 std::string response_data;
15737 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15738
15739 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15740 trans->GetTotalSentBytes());
15741 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15742 trans->GetTotalReceivedBytes());
15743}
15744
15745TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2215746 ChunkedUploadDataStream upload_data_stream(0);
15747
15748 HttpRequestInfo request;
15749 request.method = "POST";
15750 request.url = GURL("http://www.foo.com/");
15751 request.upload_data_stream = &upload_data_stream;
15752
mmenkee65e7af2015-10-13 17:16:4215753 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215754 scoped_ptr<HttpTransaction> trans(
15755 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15756 // Send headers successfully, but get an error while sending the body.
15757 MockWrite data_writes[] = {
15758 MockWrite("POST / HTTP/1.1\r\n"
15759 "Host: www.foo.com\r\n"
15760 "Connection: keep-alive\r\n"
15761 "Transfer-Encoding: chunked\r\n\r\n"),
15762 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
15763 };
15764
15765 MockRead data_reads[] = {
15766 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15767 MockRead(SYNCHRONOUS, OK),
15768 };
15769 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15770 arraysize(data_writes));
15771 session_deps_.socket_factory->AddSocketDataProvider(&data);
15772
15773 TestCompletionCallback callback;
15774
15775 EXPECT_EQ(ERR_IO_PENDING,
15776 trans->Start(&request, callback.callback(), BoundNetLog()));
15777
15778 base::RunLoop().RunUntilIdle();
15779 upload_data_stream.AppendData("f", 1, false);
15780
15781 base::RunLoop().RunUntilIdle();
15782 upload_data_stream.AppendData("oo", 2, true);
15783
15784 EXPECT_EQ(OK, callback.WaitForResult());
15785
15786 std::string response_data;
15787 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15788
15789 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15790 trans->GetTotalSentBytes());
15791 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15792 trans->GetTotalReceivedBytes());
15793}
15794
bncf4588402015-11-24 13:33:1815795TEST_P(HttpNetworkTransactionTest, EnableNPN) {
15796 session_deps_.next_protos = NextProtosDefaults();
15797 session_deps_.enable_npn = true;
15798
15799 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15800 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15801
15802 EXPECT_THAT(trans.server_ssl_config_.alpn_protos,
15803 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15804 EXPECT_THAT(trans.server_ssl_config_.npn_protos,
15805 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15806}
15807
15808TEST_P(HttpNetworkTransactionTest, DisableNPN) {
15809 session_deps_.next_protos = NextProtosDefaults();
15810 session_deps_.enable_npn = false;
15811
15812 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15813 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15814
15815 EXPECT_THAT(trans.server_ssl_config_.alpn_protos,
15816 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15817 EXPECT_TRUE(trans.server_ssl_config_.npn_protos.empty());
15818}
15819
nharperb7441ef2016-01-25 23:54:1415820#if !defined(OS_IOS)
15821TEST_P(HttpNetworkTransactionTest, TokenBindingSpdy) {
15822 const std::string https_url = "https://www.example.com";
15823 HttpRequestInfo request;
15824 request.url = GURL(https_url);
15825 request.method = "GET";
15826
15827 SSLSocketDataProvider ssl(ASYNC, OK);
15828 ssl.token_binding_negotiated = true;
15829 ssl.token_binding_key_param = TB_PARAM_ECDSAP256;
15830 ssl.SetNextProto(GetProtocol());
15831 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15832
15833 scoped_ptr<SpdyFrame> resp(
15834 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
15835 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
15836 MockRead reads[] = {CreateMockRead(*resp), CreateMockRead(*body),
15837 MockRead(ASYNC, ERR_IO_PENDING)};
15838 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
15839 session_deps_.socket_factory->AddSocketDataProvider(&data);
15840 session_deps_.channel_id_service.reset(new ChannelIDService(
15841 new DefaultChannelIDStore(nullptr), base::ThreadTaskRunnerHandle::Get()));
15842 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15843
15844 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15845 TestCompletionCallback callback;
15846 EXPECT_EQ(ERR_IO_PENDING,
15847 trans.Start(&request, callback.callback(), BoundNetLog()));
15848 base::MessageLoop::current()->RunUntilIdle();
15849
15850 EXPECT_TRUE(trans.GetResponseInfo()->was_fetched_via_spdy);
15851 HttpRequestHeaders headers;
15852 ASSERT_TRUE(trans.GetFullRequestHeaders(&headers));
15853 EXPECT_TRUE(headers.HasHeader(HttpRequestHeaders::kTokenBinding));
15854}
15855#endif // !defined(OS_IOS)
15856
[email protected]89ceba9a2009-03-21 03:46:0615857} // namespace net