blob: d54b498eceb91ea9abea0581c77b8942f2ef269c [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"
tbansal28e68f82016-02-04 02:56:1535#include "net/base/proxy_delegate.h"
[email protected]ac790b42009-12-02 04:31:3136#include "net/base/request_priority.h"
initial.commit586acc5fe2008-07-26 22:42:5237#include "net/base/test_completion_callback.h"
[email protected]42fdb452012-11-01 12:44:4038#include "net/base/test_data_directory.h"
tbansal28e68f82016-02-04 02:56:1539#include "net/base/test_proxy_delegate.h"
[email protected]b2d26cfd2012-12-11 10:36:0640#include "net/base/upload_bytes_element_reader.h"
[email protected]d98961652012-09-11 20:27:2141#include "net/base/upload_file_element_reader.h"
[email protected]6e7845ae2013-03-29 21:48:1142#include "net/cert/mock_cert_verifier.h"
[email protected]bc71b8772013-04-10 20:55:1643#include "net/dns/host_cache.h"
[email protected]f2cb3cf2013-03-21 01:40:5344#include "net/dns/mock_host_resolver.h"
[email protected]df41d0d82014-03-13 00:43:2445#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]3c32c5f2010-05-18 15:18:1246#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0047#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2948#include "net/http/http_auth_handler_ntlm.h"
aberentbba302d2015-12-03 10:20:1949#include "net/http/http_auth_scheme.h"
Adam Rice425cf122015-01-19 06:18:2450#include "net/http/http_basic_state.h"
[email protected]0877e3d2009-10-17 22:29:5751#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5252#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5653#include "net/http/http_network_session_peer.h"
Adam Rice425cf122015-01-19 06:18:2454#include "net/http/http_request_headers.h"
[email protected]17291a022011-10-10 07:32:5355#include "net/http/http_server_properties_impl.h"
[email protected]0877e3d2009-10-17 22:29:5756#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3857#include "net/http/http_stream_factory.h"
Adam Rice425cf122015-01-19 06:18:2458#include "net/http/http_stream_parser.h"
[email protected]c41737d2014-05-14 07:47:1959#include "net/http/http_transaction_test_util.h"
eroman87c53d62015-04-02 06:51:0760#include "net/log/net_log.h"
vishal.b62985ca92015-04-17 08:45:5161#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4662#include "net/log/test_net_log_entry.h"
63#include "net/log/test_net_log_util.h"
sammc5dd160c2015-04-02 02:43:1364#include "net/proxy/mock_proxy_resolver.h"
[email protected]51fff29d2008-12-19 22:17:5365#include "net/proxy/proxy_config_service_fixed.h"
[email protected]e86839fd2013-08-14 18:29:0366#include "net/proxy/proxy_info.h"
[email protected]631f1322010-04-30 17:59:1167#include "net/proxy/proxy_resolver.h"
tbansal28e68f82016-02-04 02:56:1568#include "net/proxy/proxy_server.h"
[email protected]631f1322010-04-30 17:59:1169#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4470#include "net/socket/client_socket_factory.h"
mmenked3641e12016-01-28 16:06:1571#include "net/socket/client_socket_pool.h"
[email protected]483fa202013-05-14 01:07:0372#include "net/socket/client_socket_pool_manager.h"
ttuttle1f2d7e92015-04-28 16:17:4773#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0274#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0775#include "net/socket/next_proto.h"
[email protected]f7984fc62009-06-22 23:26:4476#include "net/socket/socket_test_util.h"
77#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5478#include "net/spdy/spdy_framer.h"
79#include "net/spdy/spdy_session.h"
80#include "net/spdy/spdy_session_pool.h"
[email protected]23e482282013-06-14 16:08:0281#include "net/spdy/spdy_test_util_common.h"
nharperb7441ef2016-01-25 23:54:1482#include "net/ssl/default_channel_id_store.h"
[email protected]536fd0b2013-03-14 17:41:5783#include "net/ssl/ssl_cert_request_info.h"
[email protected]e86839fd2013-08-14 18:29:0384#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:5785#include "net/ssl/ssl_config_service_defaults.h"
86#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:5487#include "net/ssl/ssl_private_key.h"
[email protected]6e7845ae2013-03-29 21:48:1188#include "net/test/cert_test_util.h"
[email protected]831e4a32013-11-14 02:14:4489#include "net/websockets/websocket_handshake_stream_base.h"
bncf4588402015-11-24 13:33:1890#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:5291#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1592#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:2793#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:5294
[email protected]ad65a3e2013-12-25 18:18:0195using base::ASCIIToUTF16;
96
initial.commit586acc5fe2008-07-26 22:42:5297//-----------------------------------------------------------------------------
98
ttuttle859dc7a2015-04-23 19:42:2999namespace net {
100
[email protected]13c8a092010-07-29 06:15:44101namespace {
102
rdsmithebb50aa2015-11-12 03:44:38103enum TestCase {
104 // Test using the SPDY/3.1 protocol.
105 kTestCaseSPDY31,
106
107 // Test using the HTTP/2 protocol, without specifying a stream
108 // dependency based on the RequestPriority.
109 kTestCaseHTTP2NoPriorityDependencies,
110
111 // Test using the HTTP/2 protocol, specifying a stream
112 // dependency based on the RequestPriority.
113 kTestCaseHTTP2PriorityDependencies
114};
115
[email protected]42cba2fb2013-03-29 19:58:57116const base::string16 kBar(ASCIIToUTF16("bar"));
117const base::string16 kBar2(ASCIIToUTF16("bar2"));
118const base::string16 kBar3(ASCIIToUTF16("bar3"));
119const base::string16 kBaz(ASCIIToUTF16("baz"));
120const base::string16 kFirst(ASCIIToUTF16("first"));
121const base::string16 kFoo(ASCIIToUTF16("foo"));
122const base::string16 kFoo2(ASCIIToUTF16("foo2"));
123const base::string16 kFoo3(ASCIIToUTF16("foo3"));
124const base::string16 kFou(ASCIIToUTF16("fou"));
125const base::string16 kSecond(ASCIIToUTF16("second"));
126const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
127const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44128
ttuttle859dc7a2015-04-23 19:42:29129int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
130 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
131 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02132}
133
ttuttle859dc7a2015-04-23 19:42:29134int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession* session) {
135 return session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
136 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02137}
138
ttuttle859dc7a2015-04-23 19:42:29139bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
140 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
141 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52142}
143
[email protected]f3da152d2012-06-02 01:00:57144// Takes in a Value created from a NetLogHttpResponseParameter, and returns
145// a JSONified list of headers as a single string. Uses single quotes instead
146// of double quotes for easier comparison. Returns false on failure.
[email protected]ea5ef4c2013-06-13 22:50:27147bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
[email protected]f3da152d2012-06-02 01:00:57148 if (!params)
149 return false;
[email protected]ea5ef4c2013-06-13 22:50:27150 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:57151 if (!params->GetList("headers", &header_list))
152 return false;
153 std::string double_quote_headers;
estade8d046462015-05-16 01:02:34154 base::JSONWriter::Write(*header_list, &double_quote_headers);
[email protected]466c9862013-12-03 22:05:28155 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
[email protected]f3da152d2012-06-02 01:00:57156 return true;
157}
158
[email protected]029c83b62013-01-24 05:28:20159// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
160// used.
ttuttle859dc7a2015-04-23 19:42:29161void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20162 EXPECT_TRUE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29163 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25164
[email protected]029c83b62013-01-24 05:28:20165 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
166 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
167
ttuttle859dc7a2015-04-23 19:42:29168 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20169 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25170
171 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25172
[email protected]3b23a222013-05-15 21:33:25173 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25174 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
175 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25176 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25177}
178
[email protected]029c83b62013-01-24 05:28:20179// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
180// used.
ttuttle859dc7a2015-04-23 19:42:29181void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25182 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20183 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29184 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20185
186 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
187 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
188
ttuttle859dc7a2015-04-23 19:42:29189 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
190 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20191 EXPECT_LE(load_timing_info.connect_timing.connect_end,
192 load_timing_info.send_start);
193
194 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20195
[email protected]3b23a222013-05-15 21:33:25196 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20197 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
198 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25199 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20200}
201
202// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
203// used.
ttuttle859dc7a2015-04-23 19:42:29204void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20205 EXPECT_TRUE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29206 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20207
ttuttle859dc7a2015-04-23 19:42:29208 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20209
210 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
211 EXPECT_LE(load_timing_info.proxy_resolve_start,
212 load_timing_info.proxy_resolve_end);
213 EXPECT_LE(load_timing_info.proxy_resolve_end,
214 load_timing_info.send_start);
215 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20216
[email protected]3b23a222013-05-15 21:33:25217 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20218 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
219 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25220 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20221}
222
223// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
224// used.
ttuttle859dc7a2015-04-23 19:42:29225void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20226 int connect_timing_flags) {
227 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29228 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20229
230 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
231 EXPECT_LE(load_timing_info.proxy_resolve_start,
232 load_timing_info.proxy_resolve_end);
233 EXPECT_LE(load_timing_info.proxy_resolve_end,
234 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29235 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
236 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20237 EXPECT_LE(load_timing_info.connect_timing.connect_end,
238 load_timing_info.send_start);
239
240 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20241
[email protected]3b23a222013-05-15 21:33:25242 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20243 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
244 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25245 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25246}
247
ttuttle859dc7a2015-04-23 19:42:29248void AddWebSocketHeaders(HttpRequestHeaders* headers) {
Adam Rice425cf122015-01-19 06:18:24249 headers->SetHeader("Connection", "Upgrade");
250 headers->SetHeader("Upgrade", "websocket");
bncce36dca22015-04-21 22:11:23251 headers->SetHeader("Origin", "http://www.example.org");
Adam Rice425cf122015-01-19 06:18:24252 headers->SetHeader("Sec-WebSocket-Version", "13");
253 headers->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
254}
255
mmenkee65e7af2015-10-13 17:16:42256scoped_ptr<HttpNetworkSession> CreateSession(
257 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34258 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14259}
260
[email protected]448d4ca52012-03-04 04:12:23261} // namespace
262
[email protected]23e482282013-06-14 16:08:02263class HttpNetworkTransactionTest
264 : public PlatformTest,
rdsmithebb50aa2015-11-12 03:44:38265 public ::testing::WithParamInterface<TestCase> {
[email protected]483fa202013-05-14 01:07:03266 public:
[email protected]23e482282013-06-14 16:08:02267 virtual ~HttpNetworkTransactionTest() {
[email protected]483fa202013-05-14 01:07:03268 // Important to restore the per-pool limit first, since the pool limit must
269 // always be greater than group limit, and the tests reduce both limits.
270 ClientSocketPoolManager::set_max_sockets_per_pool(
271 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
272 ClientSocketPoolManager::set_max_sockets_per_group(
273 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
[email protected]483fa202013-05-14 01:07:03274 }
275
[email protected]e3ceb682011-06-28 23:55:46276 protected:
[email protected]23e482282013-06-14 16:08:02277 HttpNetworkTransactionTest()
rdsmithebb50aa2015-11-12 03:44:38278 : spdy_util_(GetProtocol(), GetDependenciesFromPriority()),
279 session_deps_(GetProtocol()),
[email protected]483fa202013-05-14 01:07:03280 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
281 HttpNetworkSession::NORMAL_SOCKET_POOL)),
282 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
283 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
rdsmith2e54d1f2016-03-21 19:48:17284 session_deps_.enable_priority_dependencies = GetDependenciesFromPriority();
[email protected]483fa202013-05-14 01:07:03285 }
[email protected]bb88e1d32013-05-03 23:11:07286
[email protected]e3ceb682011-06-28 23:55:46287 struct SimpleGetHelperResult {
288 int rv;
289 std::string status_line;
290 std::string response_data;
sclittlefb249892015-09-10 21:33:22291 int64_t total_received_bytes;
292 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25293 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47294 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59295 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46296 };
297
dcheng67be2b1f2014-10-27 21:47:29298 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50299 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34300 base::MessageLoop::current()->RunUntilIdle();
[email protected]2ff8b312010-04-26 22:20:54301 }
302
dcheng67be2b1f2014-10-27 21:47:29303 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50304 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34305 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09306 // Empty the current queue.
[email protected]2da659e2013-05-23 20:51:34307 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09308 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50309 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
[email protected]2da659e2013-05-23 20:51:34310 base::MessageLoop::current()->RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09311 }
312
rdsmithebb50aa2015-11-12 03:44:38313 NextProto GetProtocol() const {
314 return GetParam() == kTestCaseSPDY31 ? kProtoSPDY31 : kProtoHTTP2;
315 }
316
317 bool GetDependenciesFromPriority() const {
318 return GetParam() == kTestCaseHTTP2PriorityDependencies;
319 }
320
bnc33b8cef42014-11-19 17:30:38321 const char* GetAlternateProtocolFromParam() {
rdsmithebb50aa2015-11-12 03:44:38322 return AlternateProtocolToString(
323 AlternateProtocolFromNextProto(GetProtocol()));
bnc33b8cef42014-11-19 17:30:38324 }
325
bncc958faa2015-07-31 18:14:52326 std::string GetAlternativeServiceHttpHeader() {
327 return std::string("Alt-Svc: ") + GetAlternateProtocolFromParam() +
328 "=\"www.example.com:443\"\r\n";
329 }
330
[email protected]8a0fc822013-06-27 20:52:43331 std::string GetAlternateProtocolHttpHeader() {
bnc33b8cef42014-11-19 17:30:38332 return std::string("Alternate-Protocol: 443:") +
bncc958faa2015-07-31 18:14:52333 GetAlternateProtocolFromParam() + "\r\n";
[email protected]8a0fc822013-06-27 20:52:43334 }
335
[email protected]202965992011-12-07 23:04:51336 // Either |write_failure| specifies a write failure or |read_failure|
337 // specifies a read failure when using a reused socket. In either case, the
338 // failure should cause the network transaction to resend the request, and the
339 // other argument should be NULL.
340 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
341 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52342
[email protected]a34f61ee2014-03-18 20:59:49343 // Either |write_failure| specifies a write failure or |read_failure|
344 // specifies a read failure when using a reused socket. In either case, the
345 // failure should cause the network transaction to resend the request, and the
346 // other argument should be NULL.
347 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10348 const MockRead* read_failure,
349 bool use_spdy);
[email protected]a34f61ee2014-03-18 20:59:49350
[email protected]5a60c8b2011-10-19 20:14:29351 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
352 size_t data_count) {
[email protected]ff007e162009-05-23 09:13:15353 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52354
[email protected]ff007e162009-05-23 09:13:15355 HttpRequestInfo request;
356 request.method = "GET";
bncce36dca22015-04-21 22:11:23357 request.url = GURL("http://www.example.org/");
[email protected]ff007e162009-05-23 09:13:15358 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52359
vishal.b62985ca92015-04-17 08:45:51360 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07361 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:42362 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:27363 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:41364 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:27365
[email protected]5a60c8b2011-10-19 20:14:29366 for (size_t i = 0; i < data_count; ++i) {
[email protected]bb88e1d32013-05-03 23:11:07367 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
[email protected]5a60c8b2011-10-19 20:14:29368 }
initial.commit586acc5fe2008-07-26 22:42:52369
[email protected]49639fa2011-12-20 23:22:41370 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52371
eroman24bc6a12015-05-06 19:55:48372 EXPECT_TRUE(log.bound().IsCapturing());
[email protected]49639fa2011-12-20 23:22:41373 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]ff007e162009-05-23 09:13:15374 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52375
[email protected]ff007e162009-05-23 09:13:15376 out.rv = callback.WaitForResult();
sclittlefb249892015-09-10 21:33:22377 out.total_received_bytes = trans->GetTotalReceivedBytes();
378 out.total_sent_bytes = trans->GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25379
380 // Even in the failure cases that use this function, connections are always
381 // successfully established before the error.
382 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
383 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
384
[email protected]ff007e162009-05-23 09:13:15385 if (out.rv != OK)
386 return out;
387
388 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50389 // Can't use ASSERT_* inside helper functions like this, so
390 // return an error.
[email protected]90499482013-06-01 00:39:50391 if (response == NULL || response->headers.get() == NULL) {
[email protected]fe2255a2011-09-20 19:37:50392 out.rv = ERR_UNEXPECTED;
393 return out;
394 }
[email protected]ff007e162009-05-23 09:13:15395 out.status_line = response->headers->GetStatusLine();
396
[email protected]80a09a82012-11-16 17:40:06397 EXPECT_EQ("127.0.0.1", response->socket_address.host());
398 EXPECT_EQ(80, response->socket_address.port());
[email protected]6d81b482011-02-22 19:47:19399
ttuttled9dbc652015-09-29 20:00:59400 bool got_endpoint =
401 trans->GetRemoteEndpoint(&out.remote_endpoint_after_start);
402 EXPECT_EQ(got_endpoint,
403 out.remote_endpoint_after_start.address().size() > 0);
404
[email protected]ff007e162009-05-23 09:13:15405 rv = ReadTransaction(trans.get(), &out.response_data);
406 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40407
mmenke43758e62015-05-04 21:09:46408 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:40409 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39410 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40411 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12412 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39413 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40414 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39415 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
416 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15417
[email protected]f3da152d2012-06-02 01:00:57418 std::string line;
419 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
420 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
421
[email protected]79e1fd62013-06-20 06:50:04422 HttpRequestHeaders request_headers;
423 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
424 std::string value;
425 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
bncce36dca22015-04-21 22:11:23426 EXPECT_EQ("www.example.org", value);
[email protected]79e1fd62013-06-20 06:50:04427 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
428 EXPECT_EQ("keep-alive", value);
429
430 std::string response_headers;
431 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
bncce36dca22015-04-21 22:11:23432 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
[email protected]79e1fd62013-06-20 06:50:04433 response_headers);
[email protected]3deb9a52010-11-11 00:24:40434
sclittlefb249892015-09-10 21:33:22435 out.total_received_bytes = trans->GetTotalReceivedBytes();
436 // The total number of sent bytes should not have changed.
437 EXPECT_EQ(out.total_sent_bytes, trans->GetTotalSentBytes());
438
ttuttle1f2d7e92015-04-28 16:17:47439 trans->GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47440 return out;
[email protected]ff007e162009-05-23 09:13:15441 }
initial.commit586acc5fe2008-07-26 22:42:52442
[email protected]5a60c8b2011-10-19 20:14:29443 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
444 size_t reads_count) {
sclittlefb249892015-09-10 21:33:22445 MockWrite data_writes[] = {
446 MockWrite("GET / HTTP/1.1\r\n"
447 "Host: www.example.org\r\n"
448 "Connection: keep-alive\r\n\r\n"),
449 };
[email protected]5a60c8b2011-10-19 20:14:29450
sclittlefb249892015-09-10 21:33:22451 StaticSocketDataProvider reads(data_reads, reads_count, data_writes,
452 arraysize(data_writes));
453 StaticSocketDataProvider* data[] = {&reads};
454 SimpleGetHelperResult out = SimpleGetHelperForData(data, 1);
455
456 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
457 out.total_sent_bytes);
458 return out;
[email protected]b8015c42013-12-24 15:18:19459 }
460
[email protected]ff007e162009-05-23 09:13:15461 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
462 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52463
[email protected]ff007e162009-05-23 09:13:15464 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07465
466 void BypassHostCacheOnRefreshHelper(int load_flags);
467
468 void CheckErrorIsPassedBack(int error, IoMode mode);
469
[email protected]4bd46222013-05-14 19:32:23470 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07471 SpdySessionDependencies session_deps_;
[email protected]483fa202013-05-14 01:07:03472
473 // Original socket limits. Some tests set these. Safest to always restore
474 // them once each test has been run.
475 int old_max_group_sockets_;
476 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15477};
[email protected]231d5a32008-09-13 00:45:27478
rdsmithebb50aa2015-11-12 03:44:38479INSTANTIATE_TEST_CASE_P(ProtoPlusDepend,
bnc57685ae62015-03-10 21:27:20480 HttpNetworkTransactionTest,
rdsmithebb50aa2015-11-12 03:44:38481 testing::Values(kTestCaseSPDY31,
482 kTestCaseHTTP2NoPriorityDependencies,
483 kTestCaseHTTP2PriorityDependencies));
[email protected]23e482282013-06-14 16:08:02484
[email protected]448d4ca52012-03-04 04:12:23485namespace {
486
[email protected]1826a402014-01-08 15:40:48487class BeforeNetworkStartHandler {
488 public:
489 explicit BeforeNetworkStartHandler(bool defer)
490 : defer_on_before_network_start_(defer),
491 observed_before_network_start_(false) {}
492
493 void OnBeforeNetworkStart(bool* defer) {
494 *defer = defer_on_before_network_start_;
495 observed_before_network_start_ = true;
496 }
497
498 bool observed_before_network_start() const {
499 return observed_before_network_start_;
500 }
501
502 private:
503 const bool defer_on_before_network_start_;
504 bool observed_before_network_start_;
505
506 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
507};
508
[email protected]597a1ab2014-06-26 08:12:27509class BeforeProxyHeadersSentHandler {
510 public:
511 BeforeProxyHeadersSentHandler()
512 : observed_before_proxy_headers_sent_(false) {}
513
[email protected]1252d42f2014-07-01 21:20:20514 void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
515 HttpRequestHeaders* request_headers) {
[email protected]597a1ab2014-06-26 08:12:27516 observed_before_proxy_headers_sent_ = true;
517 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
518 }
519
520 bool observed_before_proxy_headers_sent() const {
521 return observed_before_proxy_headers_sent_;
522 }
523
524 std::string observed_proxy_server_uri() const {
525 return observed_proxy_server_uri_;
526 }
527
528 private:
529 bool observed_before_proxy_headers_sent_;
530 std::string observed_proxy_server_uri_;
531
532 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler);
533};
534
[email protected]15a5ccf82008-10-23 19:57:43535// Fill |str| with a long header list that consumes >= |size| bytes.
536void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51537 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19538 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
539 const int sizeof_row = strlen(row);
540 const int num_rows = static_cast<int>(
541 ceil(static_cast<float>(size) / sizeof_row));
542 const int sizeof_data = num_rows * sizeof_row;
543 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43544 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51545
[email protected]4ddaf2502008-10-23 18:26:19546 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43547 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19548}
549
thakis84dff942015-07-28 20:47:38550#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29551// Alternative functions that eliminate randomness and dependency on the local
552// host name so that the generated NTLM messages are reproducible.
avibf0746c2015-12-09 19:53:14553void MockGenerateRandom1(uint8_t* output, size_t n) {
554 static const uint8_t bytes[] = {0x55, 0x29, 0x66, 0x26,
555 0x6b, 0x9c, 0x73, 0x54};
[email protected]385a4672009-03-11 22:21:29556 static size_t current_byte = 0;
557 for (size_t i = 0; i < n; ++i) {
558 output[i] = bytes[current_byte++];
559 current_byte %= arraysize(bytes);
560 }
561}
562
avibf0746c2015-12-09 19:53:14563void MockGenerateRandom2(uint8_t* output, size_t n) {
564 static const uint8_t bytes[] = {0x96, 0x79, 0x85, 0xe7, 0x49, 0x93,
565 0x70, 0xa1, 0x4e, 0xe7, 0x87, 0x45,
566 0x31, 0x5b, 0xd3, 0x1f};
[email protected]385a4672009-03-11 22:21:29567 static size_t current_byte = 0;
568 for (size_t i = 0; i < n; ++i) {
569 output[i] = bytes[current_byte++];
570 current_byte %= arraysize(bytes);
571 }
572}
573
[email protected]fe2bc6a2009-03-23 16:52:20574std::string MockGetHostName() {
575 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29576}
thakis84dff942015-07-28 20:47:38577#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29578
[email protected]e60e47a2010-07-14 03:37:18579template<typename ParentPool>
580class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31581 public:
[email protected]9e1bdd32011-02-03 21:48:34582 CaptureGroupNameSocketPool(HostResolver* host_resolver,
583 CertVerifier* cert_verifier);
[email protected]e60e47a2010-07-14 03:37:18584
[email protected]d80a4322009-08-14 07:07:49585 const std::string last_group_name_received() const {
586 return last_group_name_;
587 }
588
dmichaeld6e570d2014-12-18 22:30:57589 int RequestSocket(const std::string& group_name,
590 const void* socket_params,
591 RequestPriority priority,
mmenked3641e12016-01-28 16:06:15592 ClientSocketPool::RespectLimits respect_limits,
dmichaeld6e570d2014-12-18 22:30:57593 ClientSocketHandle* handle,
594 const CompletionCallback& callback,
595 const BoundNetLog& net_log) override {
[email protected]04e5be32009-06-26 20:00:31596 last_group_name_ = group_name;
597 return ERR_IO_PENDING;
598 }
dmichaeld6e570d2014-12-18 22:30:57599 void CancelRequest(const std::string& group_name,
600 ClientSocketHandle* handle) override {}
601 void ReleaseSocket(const std::string& group_name,
602 scoped_ptr<StreamSocket> socket,
603 int id) override {}
604 void CloseIdleSockets() override {}
605 int IdleSocketCount() const override { return 0; }
606 int IdleSocketCountInGroup(const std::string& group_name) const override {
[email protected]04e5be32009-06-26 20:00:31607 return 0;
608 }
dmichaeld6e570d2014-12-18 22:30:57609 LoadState GetLoadState(const std::string& group_name,
610 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31611 return LOAD_STATE_IDLE;
612 }
dmichaeld6e570d2014-12-18 22:30:57613 base::TimeDelta ConnectionTimeout() const override {
[email protected]a796bcec2010-03-22 17:17:26614 return base::TimeDelta();
615 }
[email protected]d80a4322009-08-14 07:07:49616
617 private:
[email protected]04e5be32009-06-26 20:00:31618 std::string last_group_name_;
619};
620
[email protected]ab739042011-04-07 15:22:28621typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
622CaptureGroupNameTransportSocketPool;
[email protected]e772db3f2010-07-12 18:11:13623typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
624CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06625typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11626CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18627typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
628CaptureGroupNameSSLSocketPool;
629
rkaplowd90695c2015-03-25 22:12:41630template <typename ParentPool>
[email protected]e60e47a2010-07-14 03:37:18631CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34632 HostResolver* host_resolver,
633 CertVerifier* /* cert_verifier */)
rkaplowd90695c2015-03-25 22:12:41634 : ParentPool(0, 0, host_resolver, NULL, NULL) {
635}
[email protected]e60e47a2010-07-14 03:37:18636
hashimoto0d3e4fb2015-01-09 05:02:50637template <>
[email protected]2df19bb2010-08-25 20:13:46638CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
hashimotodae13b02015-01-15 04:28:21639 HostResolver* /* host_resolver */,
[email protected]9e1bdd32011-02-03 21:48:34640 CertVerifier* /* cert_verifier */)
rkaplowd90695c2015-03-25 22:12:41641 : HttpProxyClientSocketPool(0, 0, NULL, NULL, NULL) {
hashimoto0d3e4fb2015-01-09 05:02:50642}
[email protected]2df19bb2010-08-25 20:13:46643
[email protected]007b3f82013-04-09 08:46:45644template <>
[email protected]e60e47a2010-07-14 03:37:18645CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
hashimotodae13b02015-01-15 04:28:21646 HostResolver* /* host_resolver */,
[email protected]9e1bdd32011-02-03 21:48:34647 CertVerifier* cert_verifier)
[email protected]007b3f82013-04-09 08:46:45648 : SSLClientSocketPool(0,
649 0,
[email protected]007b3f82013-04-09 08:46:45650 cert_verifier,
651 NULL,
652 NULL,
[email protected]284303b62013-11-28 15:11:54653 NULL,
eranm6571b2b2014-12-03 15:53:23654 NULL,
[email protected]007b3f82013-04-09 08:46:45655 std::string(),
656 NULL,
657 NULL,
658 NULL,
659 NULL,
660 NULL,
[email protected]8e458552014-08-05 00:02:15661 NULL) {
662}
[email protected]2227c692010-05-04 15:36:11663
[email protected]231d5a32008-09-13 00:45:27664//-----------------------------------------------------------------------------
665
[email protected]79cb5c12011-09-12 13:12:04666// Helper functions for validating that AuthChallengeInfo's are correctly
667// configured for common cases.
668bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
669 if (!auth_challenge)
670 return false;
671 EXPECT_FALSE(auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:23672 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:04673 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19674 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04675 return true;
676}
677
678bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
679 if (!auth_challenge)
680 return false;
681 EXPECT_TRUE(auth_challenge->is_proxy);
682 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
683 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19684 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04685 return true;
686}
687
688bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
689 if (!auth_challenge)
690 return false;
691 EXPECT_FALSE(auth_challenge->is_proxy);
bncce36dca22015-04-21 22:11:23692 EXPECT_EQ("www.example.org:80", auth_challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:04693 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19694 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04695 return true;
696}
697
thakis84dff942015-07-28 20:47:38698#if defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04699bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
700 if (!auth_challenge)
701 return false;
702 EXPECT_FALSE(auth_challenge->is_proxy);
703 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
704 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19705 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04706 return true;
707}
thakis84dff942015-07-28 20:47:38708#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04709
[email protected]448d4ca52012-03-04 04:12:23710} // namespace
711
[email protected]23e482282013-06-14 16:08:02712TEST_P(HttpNetworkTransactionTest, Basic) {
mmenkee65e7af2015-10-13 17:16:42713 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d207a5f2009-06-04 05:28:40714 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:41715 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]231d5a32008-09-13 00:45:27716}
717
[email protected]23e482282013-06-14 16:08:02718TEST_P(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27719 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35720 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
721 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06722 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27723 };
[email protected]31a2bfe2010-02-09 08:03:39724 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
725 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42726 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27727 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
728 EXPECT_EQ("hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22729 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
730 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47731 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59732
733 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27734}
735
736// Response with no status line.
[email protected]23e482282013-06-14 16:08:02737TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27738 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35739 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06740 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27741 };
[email protected]31a2bfe2010-02-09 08:03:39742 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
743 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42744 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27745 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
746 EXPECT_EQ("hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22747 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
748 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27749}
750
751// Allow up to 4 bytes of junk to precede status line.
[email protected]23e482282013-06-14 16:08:02752TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27753 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35754 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06755 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27756 };
[email protected]31a2bfe2010-02-09 08:03:39757 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
758 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42759 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27760 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
761 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22762 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
763 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27764}
765
766// Allow up to 4 bytes of junk to precede status line.
[email protected]23e482282013-06-14 16:08:02767TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27768 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35769 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06770 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27771 };
[email protected]31a2bfe2010-02-09 08:03:39772 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
773 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42774 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27775 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
776 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22777 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
778 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27779}
780
781// Beyond 4 bytes of slop and it should fail to find a status line.
[email protected]23e482282013-06-14 16:08:02782TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27783 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35784 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06785 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27786 };
[email protected]31a2bfe2010-02-09 08:03:39787 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
788 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42789 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25790 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
791 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
sclittlefb249892015-09-10 21:33:22792 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
793 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27794}
795
796// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
[email protected]23e482282013-06-14 16:08:02797TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27798 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35799 MockRead("\n"),
800 MockRead("\n"),
801 MockRead("Q"),
802 MockRead("J"),
803 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06804 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27805 };
[email protected]31a2bfe2010-02-09 08:03:39806 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
807 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42808 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27809 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
810 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22811 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
812 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27813}
814
815// Close the connection before enough bytes to have a status line.
[email protected]23e482282013-06-14 16:08:02816TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27817 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35818 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06819 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27820 };
[email protected]31a2bfe2010-02-09 08:03:39821 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
822 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42823 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27824 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
825 EXPECT_EQ("HTT", out.response_data);
sclittlefb249892015-09-10 21:33:22826 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
827 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:52828}
829
[email protected]f9d44aa2008-09-23 23:57:17830// Simulate a 204 response, lacking a Content-Length header, sent over a
831// persistent connection. The response should still terminate since a 204
832// cannot have a response body.
[email protected]23e482282013-06-14 16:08:02833TEST_P(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:19834 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:17835 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35836 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:19837 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:06838 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:17839 };
[email protected]31a2bfe2010-02-09 08:03:39840 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
841 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42842 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17843 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
844 EXPECT_EQ("", out.response_data);
sclittlefb249892015-09-10 21:33:22845 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
846 int64_t response_size = reads_size - strlen(junk);
847 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:17848}
849
[email protected]0877e3d2009-10-17 22:29:57850// A simple request using chunked encoding with some extra data after.
[email protected]23e482282013-06-14 16:08:02851TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:19852 std::string final_chunk = "0\r\n\r\n";
853 std::string extra_data = "HTTP/1.1 200 OK\r\n";
854 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:57855 MockRead data_reads[] = {
856 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
857 MockRead("5\r\nHello\r\n"),
858 MockRead("1\r\n"),
859 MockRead(" \r\n"),
860 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:19861 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:06862 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:57863 };
[email protected]31a2bfe2010-02-09 08:03:39864 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
865 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57866 EXPECT_EQ(OK, out.rv);
867 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
868 EXPECT_EQ("Hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22869 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
870 int64_t response_size = reads_size - extra_data.size();
871 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:57872}
873
[email protected]9fe44f52010-09-23 18:36:00874// Next tests deal with http://crbug.com/56344.
875
[email protected]23e482282013-06-14 16:08:02876TEST_P(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00877 MultipleContentLengthHeadersNoTransferEncoding) {
878 MockRead data_reads[] = {
879 MockRead("HTTP/1.1 200 OK\r\n"),
880 MockRead("Content-Length: 10\r\n"),
881 MockRead("Content-Length: 5\r\n\r\n"),
882 };
883 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
884 arraysize(data_reads));
885 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
886}
887
[email protected]23e482282013-06-14 16:08:02888TEST_P(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04889 DuplicateContentLengthHeadersNoTransferEncoding) {
890 MockRead data_reads[] = {
891 MockRead("HTTP/1.1 200 OK\r\n"),
892 MockRead("Content-Length: 5\r\n"),
893 MockRead("Content-Length: 5\r\n\r\n"),
894 MockRead("Hello"),
895 };
896 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
897 arraysize(data_reads));
898 EXPECT_EQ(OK, out.rv);
899 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
900 EXPECT_EQ("Hello", out.response_data);
901}
902
[email protected]23e482282013-06-14 16:08:02903TEST_P(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04904 ComplexContentLengthHeadersNoTransferEncoding) {
905 // More than 2 dupes.
906 {
907 MockRead data_reads[] = {
908 MockRead("HTTP/1.1 200 OK\r\n"),
909 MockRead("Content-Length: 5\r\n"),
910 MockRead("Content-Length: 5\r\n"),
911 MockRead("Content-Length: 5\r\n\r\n"),
912 MockRead("Hello"),
913 };
914 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
915 arraysize(data_reads));
916 EXPECT_EQ(OK, out.rv);
917 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
918 EXPECT_EQ("Hello", out.response_data);
919 }
920 // HTTP/1.0
921 {
922 MockRead data_reads[] = {
923 MockRead("HTTP/1.0 200 OK\r\n"),
924 MockRead("Content-Length: 5\r\n"),
925 MockRead("Content-Length: 5\r\n"),
926 MockRead("Content-Length: 5\r\n\r\n"),
927 MockRead("Hello"),
928 };
929 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
930 arraysize(data_reads));
931 EXPECT_EQ(OK, out.rv);
932 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
933 EXPECT_EQ("Hello", out.response_data);
934 }
935 // 2 dupes and one mismatched.
936 {
937 MockRead data_reads[] = {
938 MockRead("HTTP/1.1 200 OK\r\n"),
939 MockRead("Content-Length: 10\r\n"),
940 MockRead("Content-Length: 10\r\n"),
941 MockRead("Content-Length: 5\r\n\r\n"),
942 };
943 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
944 arraysize(data_reads));
945 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
946 }
947}
948
[email protected]23e482282013-06-14 16:08:02949TEST_P(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00950 MultipleContentLengthHeadersTransferEncoding) {
951 MockRead data_reads[] = {
952 MockRead("HTTP/1.1 200 OK\r\n"),
953 MockRead("Content-Length: 666\r\n"),
954 MockRead("Content-Length: 1337\r\n"),
955 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
956 MockRead("5\r\nHello\r\n"),
957 MockRead("1\r\n"),
958 MockRead(" \r\n"),
959 MockRead("5\r\nworld\r\n"),
960 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:06961 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:00962 };
963 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
964 arraysize(data_reads));
965 EXPECT_EQ(OK, out.rv);
966 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
967 EXPECT_EQ("Hello world", out.response_data);
968}
969
[email protected]1628fe92011-10-04 23:04:55970// Next tests deal with http://crbug.com/98895.
971
972// Checks that a single Content-Disposition header results in no error.
[email protected]23e482282013-06-14 16:08:02973TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:55974 MockRead data_reads[] = {
975 MockRead("HTTP/1.1 200 OK\r\n"),
976 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
977 MockRead("Content-Length: 5\r\n\r\n"),
978 MockRead("Hello"),
979 };
980 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
981 arraysize(data_reads));
982 EXPECT_EQ(OK, out.rv);
983 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
984 EXPECT_EQ("Hello", out.response_data);
985}
986
[email protected]54a9c6e52012-03-21 20:10:59987// Checks that two identical Content-Disposition headers result in no error.
[email protected]23e482282013-06-14 16:08:02988TEST_P(HttpNetworkTransactionTest,
[email protected]54a9c6e52012-03-21 20:10:59989 TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:55990 MockRead data_reads[] = {
991 MockRead("HTTP/1.1 200 OK\r\n"),
992 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
993 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
994 MockRead("Content-Length: 5\r\n\r\n"),
995 MockRead("Hello"),
996 };
997 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
998 arraysize(data_reads));
[email protected]54a9c6e52012-03-21 20:10:59999 EXPECT_EQ(OK, out.rv);
1000 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1001 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551002}
1003
1004// Checks that two distinct Content-Disposition headers result in an error.
[email protected]23e482282013-06-14 16:08:021005TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551006 MockRead data_reads[] = {
1007 MockRead("HTTP/1.1 200 OK\r\n"),
1008 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1009 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1010 MockRead("Content-Length: 5\r\n\r\n"),
1011 MockRead("Hello"),
1012 };
1013 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1014 arraysize(data_reads));
1015 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
1016}
1017
[email protected]54a9c6e52012-03-21 20:10:591018// Checks that two identical Location headers result in no error.
1019// Also tests Location header behavior.
[email protected]23e482282013-06-14 16:08:021020TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551021 MockRead data_reads[] = {
1022 MockRead("HTTP/1.1 302 Redirect\r\n"),
1023 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591024 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551025 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061026 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551027 };
1028
1029 HttpRequestInfo request;
1030 request.method = "GET";
1031 request.url = GURL("http://redirect.com/");
1032 request.load_flags = 0;
1033
mmenkee65e7af2015-10-13 17:16:421034 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1628fe92011-10-04 23:04:551035 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411036 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]1628fe92011-10-04 23:04:551037
1038 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071039 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551040
[email protected]49639fa2011-12-20 23:22:411041 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551042
[email protected]49639fa2011-12-20 23:22:411043 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1628fe92011-10-04 23:04:551044 EXPECT_EQ(ERR_IO_PENDING, rv);
1045
1046 EXPECT_EQ(OK, callback.WaitForResult());
1047
1048 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501049 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
[email protected]1628fe92011-10-04 23:04:551050 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1051 std::string url;
1052 EXPECT_TRUE(response->headers->IsRedirect(&url));
1053 EXPECT_EQ("http://good.com/", url);
[email protected]d8fc4722014-06-13 13:17:151054 EXPECT_TRUE(response->proxy_server.IsEmpty());
[email protected]1628fe92011-10-04 23:04:551055}
1056
[email protected]1628fe92011-10-04 23:04:551057// Checks that two distinct Location headers result in an error.
[email protected]23e482282013-06-14 16:08:021058TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551059 MockRead data_reads[] = {
1060 MockRead("HTTP/1.1 302 Redirect\r\n"),
1061 MockRead("Location: http://good.com/\r\n"),
1062 MockRead("Location: http://evil.com/\r\n"),
1063 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061064 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551065 };
1066 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1067 arraysize(data_reads));
1068 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
1069}
1070
[email protected]ef0faf2e72009-03-05 23:27:231071// Do a request using the HEAD method. Verify that we don't try to read the
1072// message body (since HEAD has none).
[email protected]23e482282013-06-14 16:08:021073TEST_P(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421074 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231075 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231076 request.url = GURL("http://www.example.org/");
[email protected]ef0faf2e72009-03-05 23:27:231077 request.load_flags = 0;
1078
mmenkee65e7af2015-10-13 17:16:421079 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271080 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411081 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]597a1ab2014-06-26 08:12:271082 BeforeProxyHeadersSentHandler proxy_headers_handler;
1083 trans->SetBeforeProxyHeadersSentCallback(
1084 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
1085 base::Unretained(&proxy_headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271086
[email protected]ef0faf2e72009-03-05 23:27:231087 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131088 MockWrite("HEAD / HTTP/1.1\r\n"
1089 "Host: www.example.org\r\n"
1090 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231091 };
1092 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231093 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1094 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231095
mmenked39192ee2015-12-09 00:57:231096 // No response body because the test stops reading here.
1097 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231098 };
1099
[email protected]31a2bfe2010-02-09 08:03:391100 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1101 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:071102 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231103
[email protected]49639fa2011-12-20 23:22:411104 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231105
[email protected]49639fa2011-12-20 23:22:411106 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421107 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:231108
1109 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421110 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:231111
[email protected]1c773ea12009-04-28 19:58:421112 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501113 ASSERT_TRUE(response != NULL);
[email protected]ef0faf2e72009-03-05 23:27:231114
1115 // Check that the headers got parsed.
[email protected]90499482013-06-01 00:39:501116 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]ef0faf2e72009-03-05 23:27:231117 EXPECT_EQ(1234, response->headers->GetContentLength());
1118 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151119 EXPECT_TRUE(response->proxy_server.IsEmpty());
[email protected]597a1ab2014-06-26 08:12:271120 EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
[email protected]ef0faf2e72009-03-05 23:27:231121
1122 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101123 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231124 bool has_server_header = response->headers->EnumerateHeader(
1125 &iter, "Server", &server_header);
1126 EXPECT_TRUE(has_server_header);
1127 EXPECT_EQ("Blah", server_header);
1128
1129 // Reading should give EOF right away, since there is no message body
1130 // (despite non-zero content-length).
1131 std::string response_data;
1132 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421133 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:231134 EXPECT_EQ("", response_data);
1135}
1136
[email protected]23e482282013-06-14 16:08:021137TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
mmenkee65e7af2015-10-13 17:16:421138 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521139
1140 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351141 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1142 MockRead("hello"),
1143 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1144 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061145 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521146 };
[email protected]31a2bfe2010-02-09 08:03:391147 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071148 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521149
[email protected]0b0bf032010-09-21 18:08:501150 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521151 "hello", "world"
1152 };
1153
1154 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421155 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521156 request.method = "GET";
bncce36dca22015-04-21 22:11:231157 request.url = GURL("http://www.example.org/");
initial.commit586acc5fe2008-07-26 22:42:521158 request.load_flags = 0;
1159
[email protected]262eec82013-03-19 21:01:361160 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501161 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271162
[email protected]49639fa2011-12-20 23:22:411163 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521164
[email protected]49639fa2011-12-20 23:22:411165 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421166 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521167
1168 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421169 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521170
[email protected]1c773ea12009-04-28 19:58:421171 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501172 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521173
[email protected]90499482013-06-01 00:39:501174 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251175 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151176 EXPECT_TRUE(response->proxy_server.IsEmpty());
initial.commit586acc5fe2008-07-26 22:42:521177
1178 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571179 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421180 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251181 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521182 }
1183}
1184
[email protected]23e482282013-06-14 16:08:021185TEST_P(HttpNetworkTransactionTest, Ignores100) {
olli.raula6df48b2a2015-11-26 07:40:221186 std::vector<scoped_ptr<UploadElementReader>> element_readers;
1187 element_readers.push_back(
1188 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
1189 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271190
[email protected]1c773ea12009-04-28 19:58:421191 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521192 request.method = "POST";
1193 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271194 request.upload_data_stream = &upload_data_stream;
initial.commit586acc5fe2008-07-26 22:42:521195 request.load_flags = 0;
1196
mmenkee65e7af2015-10-13 17:16:421197 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271198 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411199 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271200
initial.commit586acc5fe2008-07-26 22:42:521201 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351202 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1203 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1204 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061205 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521206 };
[email protected]31a2bfe2010-02-09 08:03:391207 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071208 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521209
[email protected]49639fa2011-12-20 23:22:411210 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521211
[email protected]49639fa2011-12-20 23:22:411212 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421213 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521214
1215 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421216 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521217
[email protected]1c773ea12009-04-28 19:58:421218 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501219 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521220
[email protected]90499482013-06-01 00:39:501221 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251222 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521223
1224 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571225 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421226 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251227 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521228}
1229
[email protected]3a2d3662009-03-27 03:49:141230// This test is almost the same as Ignores100 above, but the response contains
1231// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571232// HTTP/1.1 and the two status headers are read in one read.
[email protected]23e482282013-06-14 16:08:021233TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421234 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141235 request.method = "GET";
1236 request.url = GURL("http://www.foo.com/");
1237 request.load_flags = 0;
1238
mmenkee65e7af2015-10-13 17:16:421239 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271240 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411241 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271242
[email protected]3a2d3662009-03-27 03:49:141243 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571244 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1245 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141246 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061247 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141248 };
[email protected]31a2bfe2010-02-09 08:03:391249 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071250 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141251
[email protected]49639fa2011-12-20 23:22:411252 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141253
[email protected]49639fa2011-12-20 23:22:411254 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421255 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:141256
1257 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421258 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:141259
[email protected]1c773ea12009-04-28 19:58:421260 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501261 ASSERT_TRUE(response != NULL);
[email protected]3a2d3662009-03-27 03:49:141262
[email protected]90499482013-06-01 00:39:501263 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3a2d3662009-03-27 03:49:141264 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1265
1266 std::string response_data;
1267 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421268 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:141269 EXPECT_EQ("hello world", response_data);
1270}
1271
[email protected]23e482282013-06-14 16:08:021272TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081273 HttpRequestInfo request;
1274 request.method = "POST";
1275 request.url = GURL("http://www.foo.com/");
1276 request.load_flags = 0;
1277
mmenkee65e7af2015-10-13 17:16:421278 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
zmo9528c9f42015-08-04 22:12:081279 scoped_ptr<HttpTransaction> trans(
1280 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1281
1282 MockRead data_reads[] = {
1283 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1284 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381285 };
zmo9528c9f42015-08-04 22:12:081286 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1287 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381288
zmo9528c9f42015-08-04 22:12:081289 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381290
zmo9528c9f42015-08-04 22:12:081291 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1292 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ee9410e72010-01-07 01:42:381293
zmo9528c9f42015-08-04 22:12:081294 rv = callback.WaitForResult();
1295 EXPECT_EQ(OK, rv);
[email protected]ee9410e72010-01-07 01:42:381296
zmo9528c9f42015-08-04 22:12:081297 std::string response_data;
1298 rv = ReadTransaction(trans.get(), &response_data);
1299 EXPECT_EQ(OK, rv);
1300 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381301}
1302
[email protected]23e482282013-06-14 16:08:021303TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381304 HttpRequestInfo request;
1305 request.method = "POST";
1306 request.url = GURL("http://www.foo.com/");
1307 request.load_flags = 0;
1308
mmenkee65e7af2015-10-13 17:16:421309 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271310 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411311 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271312
[email protected]ee9410e72010-01-07 01:42:381313 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061314 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381315 };
[email protected]31a2bfe2010-02-09 08:03:391316 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071317 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381318
[email protected]49639fa2011-12-20 23:22:411319 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381320
[email protected]49639fa2011-12-20 23:22:411321 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:381322 EXPECT_EQ(ERR_IO_PENDING, rv);
1323
1324 rv = callback.WaitForResult();
1325 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1326}
1327
[email protected]23e482282013-06-14 16:08:021328void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511329 const MockWrite* write_failure,
1330 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421331 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521332 request.method = "GET";
1333 request.url = GURL("http://www.foo.com/");
1334 request.load_flags = 0;
1335
vishal.b62985ca92015-04-17 08:45:511336 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071337 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421338 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271339
[email protected]202965992011-12-07 23:04:511340 // Written data for successfully sending both requests.
1341 MockWrite data1_writes[] = {
1342 MockWrite("GET / HTTP/1.1\r\n"
1343 "Host: www.foo.com\r\n"
1344 "Connection: keep-alive\r\n\r\n"),
1345 MockWrite("GET / HTTP/1.1\r\n"
1346 "Host: www.foo.com\r\n"
1347 "Connection: keep-alive\r\n\r\n")
1348 };
1349
1350 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521351 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351352 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1353 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061354 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521355 };
[email protected]202965992011-12-07 23:04:511356
1357 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491358 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511359 data1_writes[1] = *write_failure;
1360 } else {
1361 ASSERT_TRUE(read_failure);
1362 data1_reads[2] = *read_failure;
1363 }
1364
1365 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1366 data1_writes, arraysize(data1_writes));
[email protected]bb88e1d32013-05-03 23:11:071367 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521368
1369 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351370 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1371 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061372 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521373 };
[email protected]31a2bfe2010-02-09 08:03:391374 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071375 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521376
thestig9d3bb0c2015-01-24 00:49:511377 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521378 "hello", "world"
1379 };
1380
avibf0746c2015-12-09 19:53:141381 uint32_t first_socket_log_id = NetLog::Source::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521382 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411383 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521384
[email protected]262eec82013-03-19 21:01:361385 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501386 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
initial.commit586acc5fe2008-07-26 22:42:521387
[email protected]49639fa2011-12-20 23:22:411388 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421389 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521390
1391 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421392 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521393
[email protected]58e32bb2013-01-21 18:23:251394 LoadTimingInfo load_timing_info;
1395 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1396 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1397 if (i == 0) {
1398 first_socket_log_id = load_timing_info.socket_log_id;
1399 } else {
1400 // The second request should be using a new socket.
1401 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1402 }
1403
[email protected]1c773ea12009-04-28 19:58:421404 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501405 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521406
[email protected]90499482013-06-01 00:39:501407 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]3d2a59b2008-09-26 19:44:251408 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521409
1410 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571411 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421412 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251413 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521414 }
1415}
[email protected]3d2a59b2008-09-26 19:44:251416
[email protected]a34f61ee2014-03-18 20:59:491417void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1418 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101419 const MockRead* read_failure,
1420 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491421 HttpRequestInfo request;
1422 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101423 request.url = GURL("https://www.foo.com/");
[email protected]a34f61ee2014-03-18 20:59:491424 request.load_flags = 0;
1425
vishal.b62985ca92015-04-17 08:45:511426 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491427 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421428 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491429
[email protected]09356c652014-03-25 15:36:101430 SSLSocketDataProvider ssl1(ASYNC, OK);
1431 SSLSocketDataProvider ssl2(ASYNC, OK);
1432 if (use_spdy) {
rdsmithebb50aa2015-11-12 03:44:381433 ssl1.SetNextProto(GetProtocol());
1434 ssl2.SetNextProto(GetProtocol());
[email protected]09356c652014-03-25 15:36:101435 }
1436 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1437 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491438
[email protected]09356c652014-03-25 15:36:101439 // SPDY versions of the request and response.
1440 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:491441 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
[email protected]09356c652014-03-25 15:36:101442 scoped_ptr<SpdyFrame> spdy_response(
1443 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1444 scoped_ptr<SpdyFrame> spdy_data(
1445 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
[email protected]a34f61ee2014-03-18 20:59:491446
[email protected]09356c652014-03-25 15:36:101447 // HTTP/1.1 versions of the request and response.
1448 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1449 "Host: www.foo.com\r\n"
1450 "Connection: keep-alive\r\n\r\n";
1451 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1452 const char kHttpData[] = "hello";
1453
1454 std::vector<MockRead> data1_reads;
1455 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491456 if (write_failure) {
1457 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101458 data1_writes.push_back(*write_failure);
1459 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491460 } else {
1461 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101462 if (use_spdy) {
1463 data1_writes.push_back(CreateMockWrite(*spdy_request));
1464 } else {
1465 data1_writes.push_back(MockWrite(kHttpRequest));
1466 }
1467 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491468 }
1469
[email protected]09356c652014-03-25 15:36:101470 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1471 &data1_writes[0], data1_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491472 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1473
[email protected]09356c652014-03-25 15:36:101474 std::vector<MockRead> data2_reads;
1475 std::vector<MockWrite> data2_writes;
1476
1477 if (use_spdy) {
1478 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1479
1480 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1481 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1482 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1483 } else {
1484 data2_writes.push_back(
1485 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1486
1487 data2_reads.push_back(
1488 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1489 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1490 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1491 }
rch8e6c6c42015-05-01 14:05:131492 SequencedSocketData data2(&data2_reads[0], data2_reads.size(),
1493 &data2_writes[0], data2_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491494 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1495
1496 // Preconnect a socket.
ttuttle859dc7a2015-04-23 19:42:291497 SSLConfig ssl_config;
[email protected]a34f61ee2014-03-18 20:59:491498 session->ssl_config_service()->GetSSLConfig(&ssl_config);
bnc1f295372015-10-21 23:24:221499 session->GetAlpnProtos(&ssl_config.alpn_protos);
1500 session->GetNpnProtos(&ssl_config.npn_protos);
mmenked1205bd2015-07-15 22:26:351501 session->http_stream_factory()->PreconnectStreams(1, request, ssl_config,
1502 ssl_config);
[email protected]a34f61ee2014-03-18 20:59:491503 // Wait for the preconnect to complete.
1504 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1505 base::RunLoop().RunUntilIdle();
[email protected]09356c652014-03-25 15:36:101506 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491507
1508 // Make the request.
1509 TestCompletionCallback callback;
1510
1511 scoped_ptr<HttpTransaction> trans(
1512 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1513
1514 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1515 EXPECT_EQ(ERR_IO_PENDING, rv);
1516
1517 rv = callback.WaitForResult();
1518 EXPECT_EQ(OK, rv);
1519
1520 LoadTimingInfo load_timing_info;
1521 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101522 TestLoadTimingNotReused(
1523 load_timing_info,
1524 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491525
1526 const HttpResponseInfo* response = trans->GetResponseInfo();
1527 ASSERT_TRUE(response != NULL);
1528
1529 EXPECT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:021530 if (response->was_fetched_via_spdy) {
1531 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1532 } else {
1533 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1534 }
[email protected]a34f61ee2014-03-18 20:59:491535
1536 std::string response_data;
1537 rv = ReadTransaction(trans.get(), &response_data);
1538 EXPECT_EQ(OK, rv);
[email protected]09356c652014-03-25 15:36:101539 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491540}
1541
[email protected]23e482282013-06-14 16:08:021542TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:231543 KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061544 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]202965992011-12-07 23:04:511545 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1546}
1547
[email protected]23e482282013-06-14 16:08:021548TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061549 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]202965992011-12-07 23:04:511550 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251551}
1552
[email protected]23e482282013-06-14 16:08:021553TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061554 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]202965992011-12-07 23:04:511555 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251556}
1557
[email protected]d58ceea82014-06-04 10:55:541558// Make sure that on a 408 response (Request Timeout), the request is retried,
1559// if the socket was a reused keep alive socket.
1560TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1561 MockRead read_failure(SYNCHRONOUS,
1562 "HTTP/1.1 408 Request Timeout\r\n"
1563 "Connection: Keep-Alive\r\n"
1564 "Content-Length: 6\r\n\r\n"
1565 "Pickle");
1566 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1567}
1568
[email protected]a34f61ee2014-03-18 20:59:491569TEST_P(HttpNetworkTransactionTest,
1570 PreconnectErrorNotConnectedOnWrite) {
1571 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]09356c652014-03-25 15:36:101572 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
[email protected]a34f61ee2014-03-18 20:59:491573}
1574
1575TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1576 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]09356c652014-03-25 15:36:101577 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491578}
1579
1580TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1581 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]09356c652014-03-25 15:36:101582 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1583}
1584
1585TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1586 MockRead read_failure(ASYNC, OK); // EOF
1587 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1588}
1589
[email protected]d58ceea82014-06-04 10:55:541590// Make sure that on a 408 response (Request Timeout), the request is retried,
1591// if the socket was a preconnected (UNUSED_IDLE) socket.
1592TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1593 MockRead read_failure(SYNCHRONOUS,
1594 "HTTP/1.1 408 Request Timeout\r\n"
1595 "Connection: Keep-Alive\r\n"
1596 "Content-Length: 6\r\n\r\n"
1597 "Pickle");
1598 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1599 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1600}
1601
[email protected]09356c652014-03-25 15:36:101602TEST_P(HttpNetworkTransactionTest,
1603 SpdyPreconnectErrorNotConnectedOnWrite) {
1604 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1605 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1606}
1607
1608TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1609 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1610 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1611}
1612
1613TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1614 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1615 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1616}
1617
1618TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1619 MockRead read_failure(ASYNC, OK); // EOF
1620 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:491621}
1622
[email protected]23e482282013-06-14 16:08:021623TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421624 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251625 request.method = "GET";
bncce36dca22015-04-21 22:11:231626 request.url = GURL("http://www.example.org/");
[email protected]3d2a59b2008-09-26 19:44:251627 request.load_flags = 0;
1628
mmenkee65e7af2015-10-13 17:16:421629 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271630 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411631 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271632
[email protected]3d2a59b2008-09-26 19:44:251633 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061634 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:351635 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1636 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061637 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251638 };
[email protected]31a2bfe2010-02-09 08:03:391639 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071640 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:251641
[email protected]49639fa2011-12-20 23:22:411642 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:251643
[email protected]49639fa2011-12-20 23:22:411644 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421645 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:251646
1647 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421648 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
ttuttled9dbc652015-09-29 20:00:591649
1650 IPEndPoint endpoint;
1651 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
1652 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:251653}
1654
1655// What do various browsers do when the server closes a non-keepalive
1656// connection without sending any response header or body?
1657//
1658// IE7: error page
1659// Safari 3.1.2 (Windows): error page
1660// Firefox 3.0.1: blank page
1661// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:421662// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1663// Us: error page (EMPTY_RESPONSE)
[email protected]23e482282013-06-14 16:08:021664TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:251665 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061666 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:351667 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1668 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061669 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251670 };
[email protected]31a2bfe2010-02-09 08:03:391671 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1672 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:421673 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:251674}
[email protected]038e9a32008-10-08 22:40:161675
[email protected]1826a402014-01-08 15:40:481676// Test that network access can be deferred and resumed.
1677TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1678 HttpRequestInfo request;
1679 request.method = "GET";
bncce36dca22015-04-21 22:11:231680 request.url = GURL("http://www.example.org/");
[email protected]1826a402014-01-08 15:40:481681 request.load_flags = 0;
1682
mmenkee65e7af2015-10-13 17:16:421683 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1826a402014-01-08 15:40:481684 scoped_ptr<HttpTransaction> trans(
1685 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1686
1687 // Defer on OnBeforeNetworkStart.
1688 BeforeNetworkStartHandler net_start_handler(true); // defer
1689 trans->SetBeforeNetworkStartCallback(
1690 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1691 base::Unretained(&net_start_handler)));
1692
1693 MockRead data_reads[] = {
1694 MockRead("HTTP/1.0 200 OK\r\n"),
1695 MockRead("Content-Length: 5\r\n\r\n"),
1696 MockRead("hello"),
1697 MockRead(SYNCHRONOUS, 0),
1698 };
1699 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1700 session_deps_.socket_factory->AddSocketDataProvider(&data);
1701
1702 TestCompletionCallback callback;
1703
1704 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1705 EXPECT_EQ(ERR_IO_PENDING, rv);
1706 base::MessageLoop::current()->RunUntilIdle();
1707
1708 // Should have deferred for network start.
1709 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1710 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
[email protected]1826a402014-01-08 15:40:481711
1712 trans->ResumeNetworkStart();
1713 rv = callback.WaitForResult();
1714 EXPECT_EQ(OK, rv);
1715 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1716
1717 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1718 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1719 if (rv == ERR_IO_PENDING)
1720 rv = callback.WaitForResult();
1721 EXPECT_EQ(5, rv);
1722 trans.reset();
1723}
1724
1725// Test that network use can be deferred and canceled.
1726TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1727 HttpRequestInfo request;
1728 request.method = "GET";
bncce36dca22015-04-21 22:11:231729 request.url = GURL("http://www.example.org/");
[email protected]1826a402014-01-08 15:40:481730 request.load_flags = 0;
1731
mmenkee65e7af2015-10-13 17:16:421732 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1826a402014-01-08 15:40:481733 scoped_ptr<HttpTransaction> trans(
1734 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1735
1736 // Defer on OnBeforeNetworkStart.
1737 BeforeNetworkStartHandler net_start_handler(true); // defer
1738 trans->SetBeforeNetworkStartCallback(
1739 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1740 base::Unretained(&net_start_handler)));
1741
1742 TestCompletionCallback callback;
1743
1744 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1745 EXPECT_EQ(ERR_IO_PENDING, rv);
1746 base::MessageLoop::current()->RunUntilIdle();
1747
1748 // Should have deferred for network start.
1749 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1750 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
[email protected]1826a402014-01-08 15:40:481751}
1752
[email protected]7a5378b2012-11-04 03:25:171753// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1754// tests. There was a bug causing HttpNetworkTransaction to hang in the
1755// destructor in such situations.
1756// See http://crbug.com/154712 and http://crbug.com/156609.
[email protected]23e482282013-06-14 16:08:021757TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:171758 HttpRequestInfo request;
1759 request.method = "GET";
bncce36dca22015-04-21 22:11:231760 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171761 request.load_flags = 0;
1762
mmenkee65e7af2015-10-13 17:16:421763 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:361764 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501765 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171766
1767 MockRead data_reads[] = {
1768 MockRead("HTTP/1.0 200 OK\r\n"),
1769 MockRead("Connection: keep-alive\r\n"),
1770 MockRead("Content-Length: 100\r\n\r\n"),
1771 MockRead("hello"),
1772 MockRead(SYNCHRONOUS, 0),
1773 };
1774 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071775 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171776
1777 TestCompletionCallback callback;
1778
1779 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1780 EXPECT_EQ(ERR_IO_PENDING, rv);
1781
1782 rv = callback.WaitForResult();
1783 EXPECT_EQ(OK, rv);
1784
1785 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501786 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171787 if (rv == ERR_IO_PENDING)
1788 rv = callback.WaitForResult();
1789 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:501790 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171791 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1792
1793 trans.reset();
[email protected]2da659e2013-05-23 20:51:341794 base::MessageLoop::current()->RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171795 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1796}
1797
[email protected]23e482282013-06-14 16:08:021798TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:171799 HttpRequestInfo request;
1800 request.method = "GET";
bncce36dca22015-04-21 22:11:231801 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171802 request.load_flags = 0;
1803
mmenkee65e7af2015-10-13 17:16:421804 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:361805 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501806 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171807
1808 MockRead data_reads[] = {
1809 MockRead("HTTP/1.0 200 OK\r\n"),
1810 MockRead("Connection: keep-alive\r\n"),
1811 MockRead("Content-Length: 100\r\n\r\n"),
1812 MockRead(SYNCHRONOUS, 0),
1813 };
1814 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071815 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171816
1817 TestCompletionCallback callback;
1818
1819 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1820 EXPECT_EQ(ERR_IO_PENDING, rv);
1821
1822 rv = callback.WaitForResult();
1823 EXPECT_EQ(OK, rv);
1824
1825 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501826 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171827 if (rv == ERR_IO_PENDING)
1828 rv = callback.WaitForResult();
1829 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1830
1831 trans.reset();
[email protected]2da659e2013-05-23 20:51:341832 base::MessageLoop::current()->RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171833 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1834}
1835
[email protected]0b0bf032010-09-21 18:08:501836// Test that we correctly reuse a keep-alive connection after not explicitly
1837// reading the body.
[email protected]23e482282013-06-14 16:08:021838TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:131839 HttpRequestInfo request;
1840 request.method = "GET";
1841 request.url = GURL("http://www.foo.com/");
1842 request.load_flags = 0;
1843
vishal.b62985ca92015-04-17 08:45:511844 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071845 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:421846 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271847
mmenkecc2298e2015-12-07 18:20:181848 const char* request_data =
1849 "GET / HTTP/1.1\r\n"
1850 "Host: www.foo.com\r\n"
1851 "Connection: keep-alive\r\n\r\n";
1852 MockWrite data_writes[] = {
1853 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
1854 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
1855 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
1856 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
1857 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
1858 };
1859
[email protected]0b0bf032010-09-21 18:08:501860 // Note that because all these reads happen in the same
1861 // StaticSocketDataProvider, it shows that the same socket is being reused for
1862 // all transactions.
mmenkecc2298e2015-12-07 18:20:181863 MockRead data_reads[] = {
1864 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
1865 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
1866 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
1867 MockRead(ASYNC, 7,
1868 "HTTP/1.1 302 Found\r\n"
1869 "Content-Length: 0\r\n\r\n"),
1870 MockRead(ASYNC, 9,
1871 "HTTP/1.1 302 Found\r\n"
1872 "Content-Length: 5\r\n\r\n"
1873 "hello"),
1874 MockRead(ASYNC, 11,
1875 "HTTP/1.1 301 Moved Permanently\r\n"
1876 "Content-Length: 0\r\n\r\n"),
1877 MockRead(ASYNC, 13,
1878 "HTTP/1.1 301 Moved Permanently\r\n"
1879 "Content-Length: 5\r\n\r\n"
1880 "hello"),
[email protected]fc31d6a42010-06-24 18:05:131881
mmenkecc2298e2015-12-07 18:20:181882 // In the next two rounds, IsConnectedAndIdle returns false, due to
1883 // the set_busy_before_sync_reads(true) call, while the
1884 // HttpNetworkTransaction is being shut down, but the socket is still
1885 // reuseable. See http://crbug.com/544255.
1886 MockRead(ASYNC, 15,
1887 "HTTP/1.1 200 Hunky-Dory\r\n"
1888 "Content-Length: 5\r\n\r\n"),
1889 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:131890
mmenkecc2298e2015-12-07 18:20:181891 MockRead(ASYNC, 18,
1892 "HTTP/1.1 200 Hunky-Dory\r\n"
1893 "Content-Length: 5\r\n\r\n"
1894 "he"),
1895 MockRead(SYNCHRONOUS, 19, "llo"),
1896
1897 // The body of the final request is actually read.
1898 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1899 MockRead(ASYNC, 22, "hello"),
1900 };
1901 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
1902 arraysize(data_writes));
1903 data.set_busy_before_sync_reads(true);
1904 session_deps_.socket_factory->AddSocketDataProvider(&data);
1905
1906 const int kNumUnreadBodies = arraysize(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:501907 std::string response_lines[kNumUnreadBodies];
1908
avibf0746c2015-12-09 19:53:141909 uint32_t first_socket_log_id = NetLog::Source::kInvalidId;
mmenkecc2298e2015-12-07 18:20:181910 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:411911 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:131912
[email protected]262eec82013-03-19 21:01:361913 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501914 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]fc31d6a42010-06-24 18:05:131915
[email protected]49639fa2011-12-20 23:22:411916 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
mmenkecc2298e2015-12-07 18:20:181917 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]fc31d6a42010-06-24 18:05:131918
[email protected]58e32bb2013-01-21 18:23:251919 LoadTimingInfo load_timing_info;
1920 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1921 if (i == 0) {
1922 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1923 first_socket_log_id = load_timing_info.socket_log_id;
1924 } else {
1925 TestLoadTimingReused(load_timing_info);
1926 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1927 }
1928
[email protected]fc31d6a42010-06-24 18:05:131929 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:181930 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:131931
mmenkecc2298e2015-12-07 18:20:181932 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:501933 response_lines[i] = response->headers->GetStatusLine();
1934
mmenkecc2298e2015-12-07 18:20:181935 // Delete the transaction without reading the response bodies. Then spin
1936 // the message loop, so the response bodies are drained.
1937 trans.reset();
1938 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:131939 }
[email protected]0b0bf032010-09-21 18:08:501940
1941 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:181942 "HTTP/1.1 204 No Content",
1943 "HTTP/1.1 205 Reset Content",
1944 "HTTP/1.1 304 Not Modified",
1945 "HTTP/1.1 302 Found",
1946 "HTTP/1.1 302 Found",
1947 "HTTP/1.1 301 Moved Permanently",
1948 "HTTP/1.1 301 Moved Permanently",
1949 "HTTP/1.1 200 Hunky-Dory",
1950 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:501951 };
1952
mostynb91e0da982015-01-20 19:17:271953 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1954 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:501955
1956 for (int i = 0; i < kNumUnreadBodies; ++i)
1957 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1958
[email protected]49639fa2011-12-20 23:22:411959 TestCompletionCallback callback;
[email protected]262eec82013-03-19 21:01:361960 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501961 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:411962 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
mmenkecc2298e2015-12-07 18:20:181963 EXPECT_EQ(OK, callback.GetResult(rv));
[email protected]0b0bf032010-09-21 18:08:501964 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:181965 ASSERT_TRUE(response);
1966 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:501967 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1968 std::string response_data;
1969 rv = ReadTransaction(trans.get(), &response_data);
1970 EXPECT_EQ(OK, rv);
1971 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131972}
1973
[email protected]038e9a32008-10-08 22:40:161974// Test the request-challenge-retry sequence for basic auth.
1975// (basic auth is the easiest to mock, because it has no randomness).
[email protected]23e482282013-06-14 16:08:021976TEST_P(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421977 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161978 request.method = "GET";
bncce36dca22015-04-21 22:11:231979 request.url = GURL("http://www.example.org/");
[email protected]038e9a32008-10-08 22:40:161980 request.load_flags = 0;
1981
vishal.b62985ca92015-04-17 08:45:511982 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:071983 session_deps_.net_log = &log;
mmenkee65e7af2015-10-13 17:16:421984 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271985 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411986 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271987
[email protected]f9ee6b52008-11-08 06:46:231988 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:231989 MockWrite(
1990 "GET / HTTP/1.1\r\n"
1991 "Host: www.example.org\r\n"
1992 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:231993 };
1994
[email protected]038e9a32008-10-08 22:40:161995 MockRead data_reads1[] = {
1996 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1997 // Give a couple authenticate options (only the middle one is actually
1998 // supported).
[email protected]22927ad2009-09-21 19:56:191999 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162000 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2001 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2002 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2003 // Large content-length -- won't matter, as connection will be reset.
2004 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062005 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162006 };
2007
2008 // After calling trans->RestartWithAuth(), this is the request we should
2009 // be issuing -- the final header line contains the credentials.
2010 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232011 MockWrite(
2012 "GET / HTTP/1.1\r\n"
2013 "Host: www.example.org\r\n"
2014 "Connection: keep-alive\r\n"
2015 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162016 };
2017
2018 // Lastly, the server responds with the actual content.
2019 MockRead data_reads2[] = {
2020 MockRead("HTTP/1.0 200 OK\r\n"),
2021 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2022 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062023 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162024 };
2025
[email protected]31a2bfe2010-02-09 08:03:392026 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2027 data_writes1, arraysize(data_writes1));
2028 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2029 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:072030 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2031 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162032
[email protected]49639fa2011-12-20 23:22:412033 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162034
[email protected]49639fa2011-12-20 23:22:412035 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422036 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162037
2038 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422039 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162040
[email protected]58e32bb2013-01-21 18:23:252041 LoadTimingInfo load_timing_info1;
2042 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2043 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2044
sclittlefb249892015-09-10 21:33:222045 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2046 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2047 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
[email protected]b8015c42013-12-24 15:18:192048 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2049
[email protected]1c773ea12009-04-28 19:58:422050 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502051 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042052 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162053
[email protected]49639fa2011-12-20 23:22:412054 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162055
[email protected]49639fa2011-12-20 23:22:412056 rv = trans->RestartWithAuth(
2057 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422058 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162059
2060 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422061 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162062
[email protected]58e32bb2013-01-21 18:23:252063 LoadTimingInfo load_timing_info2;
2064 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2065 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2066 // The load timing after restart should have a new socket ID, and times after
2067 // those of the first load timing.
2068 EXPECT_LE(load_timing_info1.receive_headers_end,
2069 load_timing_info2.connect_timing.connect_start);
2070 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2071
sclittlefb249892015-09-10 21:33:222072 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2073 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2074 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
[email protected]b8015c42013-12-24 15:18:192075 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2076
[email protected]038e9a32008-10-08 22:40:162077 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502078 ASSERT_TRUE(response != NULL);
[email protected]038e9a32008-10-08 22:40:162079 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2080 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162081}
2082
ttuttled9dbc652015-09-29 20:00:592083// Test the request-challenge-retry sequence for basic auth.
2084// (basic auth is the easiest to mock, because it has no randomness).
2085TEST_P(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
2086 HttpRequestInfo request;
2087 request.method = "GET";
2088 request.url = GURL("http://www.example.org/");
2089 request.load_flags = 0;
2090
2091 TestNetLog log;
2092 MockHostResolver* resolver = new MockHostResolver();
2093 session_deps_.net_log = &log;
2094 session_deps_.host_resolver.reset(resolver);
mmenkee65e7af2015-10-13 17:16:422095 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
ttuttled9dbc652015-09-29 20:00:592096 scoped_ptr<HttpTransaction> trans(
2097 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2098
2099 resolver->rules()->ClearRules();
2100 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2101
2102 MockWrite data_writes1[] = {
2103 MockWrite("GET / HTTP/1.1\r\n"
2104 "Host: www.example.org\r\n"
2105 "Connection: keep-alive\r\n\r\n"),
2106 };
2107
2108 MockRead data_reads1[] = {
2109 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2110 // Give a couple authenticate options (only the middle one is actually
2111 // supported).
2112 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2113 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2114 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2115 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2116 // Large content-length -- won't matter, as connection will be reset.
2117 MockRead("Content-Length: 10000\r\n\r\n"),
2118 MockRead(SYNCHRONOUS, ERR_FAILED),
2119 };
2120
2121 // After calling trans->RestartWithAuth(), this is the request we should
2122 // be issuing -- the final header line contains the credentials.
2123 MockWrite data_writes2[] = {
2124 MockWrite("GET / HTTP/1.1\r\n"
2125 "Host: www.example.org\r\n"
2126 "Connection: keep-alive\r\n"
2127 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2128 };
2129
2130 // Lastly, the server responds with the actual content.
2131 MockRead data_reads2[] = {
2132 MockRead("HTTP/1.0 200 OK\r\n"),
2133 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2134 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2135 };
2136
2137 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2138 data_writes1, arraysize(data_writes1));
2139 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2140 data_writes2, arraysize(data_writes2));
2141 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2142 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2143
2144 TestCompletionCallback callback1;
2145
2146 EXPECT_EQ(OK, callback1.GetResult(trans->Start(&request, callback1.callback(),
2147 BoundNetLog())));
2148
2149 LoadTimingInfo load_timing_info1;
2150 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2151 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2152
2153 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2154 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2155 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
2156 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2157
2158 const HttpResponseInfo* response = trans->GetResponseInfo();
2159 ASSERT_TRUE(response);
2160 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2161
2162 IPEndPoint endpoint;
2163 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2164 ASSERT_FALSE(endpoint.address().empty());
2165 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2166
2167 resolver->rules()->ClearRules();
2168 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2169
2170 TestCompletionCallback callback2;
2171
2172 EXPECT_EQ(OK, callback2.GetResult(trans->RestartWithAuth(
2173 AuthCredentials(kFoo, kBar), callback2.callback())));
2174
2175 LoadTimingInfo load_timing_info2;
2176 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2177 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2178 // The load timing after restart should have a new socket ID, and times after
2179 // those of the first load timing.
2180 EXPECT_LE(load_timing_info1.receive_headers_end,
2181 load_timing_info2.connect_timing.connect_start);
2182 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2183
2184 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2185 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2186 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
2187 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2188
2189 response = trans->GetResponseInfo();
2190 ASSERT_TRUE(response);
2191 EXPECT_FALSE(response->auth_challenge.get());
2192 EXPECT_EQ(100, response->headers->GetContentLength());
2193
2194 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2195 ASSERT_FALSE(endpoint.address().empty());
2196 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2197}
2198
[email protected]23e482282013-06-14 16:08:022199TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462200 HttpRequestInfo request;
2201 request.method = "GET";
bncce36dca22015-04-21 22:11:232202 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292203 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]861fcd52009-08-26 02:33:462204
mmenkee65e7af2015-10-13 17:16:422205 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272206 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:412207 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:272208
[email protected]861fcd52009-08-26 02:33:462209 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232210 MockWrite(
2211 "GET / HTTP/1.1\r\n"
2212 "Host: www.example.org\r\n"
2213 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462214 };
2215
2216 MockRead data_reads[] = {
2217 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2218 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2219 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2220 // Large content-length -- won't matter, as connection will be reset.
2221 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062222 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462223 };
2224
[email protected]31a2bfe2010-02-09 08:03:392225 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2226 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:072227 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412228 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462229
[email protected]49639fa2011-12-20 23:22:412230 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]861fcd52009-08-26 02:33:462231 EXPECT_EQ(ERR_IO_PENDING, rv);
2232
2233 rv = callback.WaitForResult();
2234 EXPECT_EQ(0, rv);
2235
sclittlefb249892015-09-10 21:33:222236 int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes));
2237 EXPECT_EQ(writes_size, trans->GetTotalSentBytes());
2238 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
[email protected]b8015c42013-12-24 15:18:192239 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2240
[email protected]861fcd52009-08-26 02:33:462241 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502242 ASSERT_TRUE(response != NULL);
[email protected]861fcd52009-08-26 02:33:462243 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2244}
2245
[email protected]2d2697f92009-02-18 21:00:322246// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2247// connection.
[email protected]23e482282013-06-14 16:08:022248TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182249 // On the second pass, the body read of the auth challenge is synchronous, so
2250 // IsConnectedAndIdle returns false. The socket should still be drained and
2251 // reused. See http://crbug.com/544255.
2252 for (int i = 0; i < 2; ++i) {
2253 HttpRequestInfo request;
2254 request.method = "GET";
2255 request.url = GURL("http://www.example.org/");
2256 request.load_flags = 0;
[email protected]2d2697f92009-02-18 21:00:322257
mmenkecc2298e2015-12-07 18:20:182258 TestNetLog log;
2259 session_deps_.net_log = &log;
2260 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272261
mmenkecc2298e2015-12-07 18:20:182262 MockWrite data_writes[] = {
2263 MockWrite(ASYNC, 0,
2264 "GET / HTTP/1.1\r\n"
2265 "Host: www.example.org\r\n"
2266 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322267
mmenkecc2298e2015-12-07 18:20:182268 // After calling trans->RestartWithAuth(), this is the request we should
2269 // be issuing -- the final header line contains the credentials.
2270 MockWrite(ASYNC, 6,
2271 "GET / HTTP/1.1\r\n"
2272 "Host: www.example.org\r\n"
2273 "Connection: keep-alive\r\n"
2274 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2275 };
[email protected]2d2697f92009-02-18 21:00:322276
mmenkecc2298e2015-12-07 18:20:182277 MockRead data_reads[] = {
2278 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2279 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2280 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2281 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2282 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322283
mmenkecc2298e2015-12-07 18:20:182284 // Lastly, the server responds with the actual content.
2285 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2286 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2287 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2288 MockRead(ASYNC, 10, "Hello"),
2289 };
[email protected]2d2697f92009-02-18 21:00:322290
mmenkecc2298e2015-12-07 18:20:182291 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
2292 arraysize(data_writes));
2293 data.set_busy_before_sync_reads(true);
2294 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:462295
mmenkecc2298e2015-12-07 18:20:182296 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322297
mmenkecc2298e2015-12-07 18:20:182298 scoped_ptr<HttpTransaction> trans(
2299 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2300 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2301 ASSERT_EQ(OK, callback1.GetResult(rv));
[email protected]2d2697f92009-02-18 21:00:322302
mmenkecc2298e2015-12-07 18:20:182303 LoadTimingInfo load_timing_info1;
2304 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2305 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:322306
mmenkecc2298e2015-12-07 18:20:182307 const HttpResponseInfo* response = trans->GetResponseInfo();
2308 ASSERT_TRUE(response);
2309 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322310
mmenkecc2298e2015-12-07 18:20:182311 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:252312
mmenkecc2298e2015-12-07 18:20:182313 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
2314 callback2.callback());
2315 ASSERT_EQ(OK, callback2.GetResult(rv));
[email protected]2d2697f92009-02-18 21:00:322316
mmenkecc2298e2015-12-07 18:20:182317 LoadTimingInfo load_timing_info2;
2318 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2319 TestLoadTimingReused(load_timing_info2);
2320 // The load timing after restart should have the same socket ID, and times
2321 // those of the first load timing.
2322 EXPECT_LE(load_timing_info1.receive_headers_end,
2323 load_timing_info2.send_start);
2324 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:322325
mmenkecc2298e2015-12-07 18:20:182326 response = trans->GetResponseInfo();
2327 ASSERT_TRUE(response);
2328 EXPECT_FALSE(response->auth_challenge);
2329 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322330
mmenkecc2298e2015-12-07 18:20:182331 std::string response_data;
2332 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]2d2697f92009-02-18 21:00:322333
mmenkecc2298e2015-12-07 18:20:182334 int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes));
2335 EXPECT_EQ(writes_size, trans->GetTotalSentBytes());
2336 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
2337 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2338 }
[email protected]2d2697f92009-02-18 21:00:322339}
2340
2341// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2342// connection and with no response body to drain.
[email protected]23e482282013-06-14 16:08:022343TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:422344 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322345 request.method = "GET";
bncce36dca22015-04-21 22:11:232346 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322347 request.load_flags = 0;
2348
mmenkee65e7af2015-10-13 17:16:422349 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272350
[email protected]2d2697f92009-02-18 21:00:322351 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232352 MockWrite(
2353 "GET / HTTP/1.1\r\n"
2354 "Host: www.example.org\r\n"
2355 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322356
bncce36dca22015-04-21 22:11:232357 // After calling trans->RestartWithAuth(), this is the request we should
2358 // be issuing -- the final header line contains the credentials.
2359 MockWrite(
2360 "GET / HTTP/1.1\r\n"
2361 "Host: www.example.org\r\n"
2362 "Connection: keep-alive\r\n"
2363 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322364 };
2365
[email protected]2d2697f92009-02-18 21:00:322366 MockRead data_reads1[] = {
2367 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2368 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:312369 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:322370
2371 // Lastly, the server responds with the actual content.
2372 MockRead("HTTP/1.1 200 OK\r\n"),
2373 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502374 MockRead("Content-Length: 5\r\n\r\n"),
2375 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322376 };
2377
[email protected]2d0a4f92011-05-05 16:38:462378 // An incorrect reconnect would cause this to be read.
2379 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062380 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462381 };
2382
[email protected]31a2bfe2010-02-09 08:03:392383 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2384 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462385 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2386 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072387 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2388 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322389
[email protected]49639fa2011-12-20 23:22:412390 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322391
[email protected]262eec82013-03-19 21:01:362392 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502393 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412394 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422395 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322396
2397 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422398 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322399
[email protected]1c773ea12009-04-28 19:58:422400 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502401 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042402 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322403
[email protected]49639fa2011-12-20 23:22:412404 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322405
[email protected]49639fa2011-12-20 23:22:412406 rv = trans->RestartWithAuth(
2407 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422408 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322409
2410 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422411 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322412
2413 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502414 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322415 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502416 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322417}
2418
2419// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2420// connection and with a large response body to drain.
[email protected]23e482282013-06-14 16:08:022421TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:422422 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322423 request.method = "GET";
bncce36dca22015-04-21 22:11:232424 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322425 request.load_flags = 0;
2426
mmenkee65e7af2015-10-13 17:16:422427 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272428
[email protected]2d2697f92009-02-18 21:00:322429 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232430 MockWrite(
2431 "GET / HTTP/1.1\r\n"
2432 "Host: www.example.org\r\n"
2433 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322434
bncce36dca22015-04-21 22:11:232435 // After calling trans->RestartWithAuth(), this is the request we should
2436 // be issuing -- the final header line contains the credentials.
2437 MockWrite(
2438 "GET / HTTP/1.1\r\n"
2439 "Host: www.example.org\r\n"
2440 "Connection: keep-alive\r\n"
2441 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322442 };
2443
2444 // Respond with 5 kb of response body.
2445 std::string large_body_string("Unauthorized");
2446 large_body_string.append(5 * 1024, ' ');
2447 large_body_string.append("\r\n");
2448
2449 MockRead data_reads1[] = {
2450 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2451 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2452 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2453 // 5134 = 12 + 5 * 1024 + 2
2454 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062455 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:322456
2457 // Lastly, the server responds with the actual content.
2458 MockRead("HTTP/1.1 200 OK\r\n"),
2459 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502460 MockRead("Content-Length: 5\r\n\r\n"),
2461 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322462 };
2463
[email protected]2d0a4f92011-05-05 16:38:462464 // An incorrect reconnect would cause this to be read.
2465 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062466 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462467 };
2468
[email protected]31a2bfe2010-02-09 08:03:392469 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2470 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462471 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2472 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072473 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2474 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322475
[email protected]49639fa2011-12-20 23:22:412476 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322477
[email protected]262eec82013-03-19 21:01:362478 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502479 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412480 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422481 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322482
2483 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422484 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322485
[email protected]1c773ea12009-04-28 19:58:422486 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502487 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042488 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322489
[email protected]49639fa2011-12-20 23:22:412490 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322491
[email protected]49639fa2011-12-20 23:22:412492 rv = trans->RestartWithAuth(
2493 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422494 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:322495
2496 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422497 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:322498
2499 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502500 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:322501 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502502 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322503}
2504
2505// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:312506// connection, but the server gets impatient and closes the connection.
[email protected]23e482282013-06-14 16:08:022507TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:312508 HttpRequestInfo request;
2509 request.method = "GET";
bncce36dca22015-04-21 22:11:232510 request.url = GURL("http://www.example.org/");
[email protected]11203f012009-11-12 23:02:312511 request.load_flags = 0;
2512
mmenkee65e7af2015-10-13 17:16:422513 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272514
[email protected]11203f012009-11-12 23:02:312515 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232516 MockWrite(
2517 "GET / HTTP/1.1\r\n"
2518 "Host: www.example.org\r\n"
2519 "Connection: keep-alive\r\n\r\n"),
2520 // This simulates the seemingly successful write to a closed connection
2521 // if the bug is not fixed.
2522 MockWrite(
2523 "GET / HTTP/1.1\r\n"
2524 "Host: www.example.org\r\n"
2525 "Connection: keep-alive\r\n"
2526 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312527 };
2528
2529 MockRead data_reads1[] = {
2530 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2531 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2532 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2533 MockRead("Content-Length: 14\r\n\r\n"),
2534 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:062535 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:312536 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:062537 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:312538 };
2539
2540 // After calling trans->RestartWithAuth(), this is the request we should
2541 // be issuing -- the final header line contains the credentials.
2542 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232543 MockWrite(
2544 "GET / HTTP/1.1\r\n"
2545 "Host: www.example.org\r\n"
2546 "Connection: keep-alive\r\n"
2547 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312548 };
2549
2550 // Lastly, the server responds with the actual content.
2551 MockRead data_reads2[] = {
2552 MockRead("HTTP/1.1 200 OK\r\n"),
2553 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502554 MockRead("Content-Length: 5\r\n\r\n"),
2555 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:312556 };
2557
[email protected]31a2bfe2010-02-09 08:03:392558 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2559 data_writes1, arraysize(data_writes1));
2560 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2561 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:072562 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2563 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:312564
[email protected]49639fa2011-12-20 23:22:412565 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:312566
[email protected]262eec82013-03-19 21:01:362567 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502568 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412569 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]11203f012009-11-12 23:02:312570 EXPECT_EQ(ERR_IO_PENDING, rv);
2571
2572 rv = callback1.WaitForResult();
2573 EXPECT_EQ(OK, rv);
2574
2575 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502576 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042577 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]11203f012009-11-12 23:02:312578
[email protected]49639fa2011-12-20 23:22:412579 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:312580
[email protected]49639fa2011-12-20 23:22:412581 rv = trans->RestartWithAuth(
2582 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]11203f012009-11-12 23:02:312583 EXPECT_EQ(ERR_IO_PENDING, rv);
2584
2585 rv = callback2.WaitForResult();
2586 EXPECT_EQ(OK, rv);
2587
2588 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502589 ASSERT_TRUE(response != NULL);
[email protected]11203f012009-11-12 23:02:312590 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502591 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:312592}
2593
[email protected]394816e92010-08-03 07:38:592594// Test the request-challenge-retry sequence for basic auth, over a connection
2595// that requires a restart when setting up an SSL tunnel.
ttuttle34f63b52015-03-05 04:33:012596TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
2597 HttpRequestInfo request;
2598 request.method = "GET";
bncce36dca22015-04-21 22:11:232599 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:012600 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292601 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:012602
2603 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032604 session_deps_.proxy_service =
2605 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512606 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:012607 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:422608 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:012609
2610 // Since we have proxy, should try to establish tunnel.
2611 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542612 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172613 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542614 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:012615 };
2616
mmenkee71e15332015-10-07 16:39:542617 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:012618 // connection.
2619 MockRead data_reads1[] = {
2620 // No credentials.
2621 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2622 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:542623 };
ttuttle34f63b52015-03-05 04:33:012624
mmenkee71e15332015-10-07 16:39:542625 // Since the first connection couldn't be reused, need to establish another
2626 // once given credentials.
2627 MockWrite data_writes2[] = {
2628 // After calling trans->RestartWithAuth(), this is the request we should
2629 // be issuing -- the final header line contains the credentials.
2630 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172631 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542632 "Proxy-Connection: keep-alive\r\n"
2633 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2634
2635 MockWrite("GET / HTTP/1.1\r\n"
2636 "Host: www.example.org\r\n"
2637 "Connection: keep-alive\r\n\r\n"),
2638 };
2639
2640 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:012641 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2642
2643 MockRead("HTTP/1.1 200 OK\r\n"),
2644 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2645 MockRead("Content-Length: 5\r\n\r\n"),
2646 MockRead(SYNCHRONOUS, "hello"),
2647 };
2648
2649 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2650 data_writes1, arraysize(data_writes1));
2651 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542652 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2653 data_writes2, arraysize(data_writes2));
2654 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:012655 SSLSocketDataProvider ssl(ASYNC, OK);
2656 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2657
2658 TestCompletionCallback callback1;
2659
2660 scoped_ptr<HttpTransaction> trans(
2661 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2662
2663 int rv = trans->Start(&request, callback1.callback(), log.bound());
2664 EXPECT_EQ(ERR_IO_PENDING, rv);
2665
2666 rv = callback1.WaitForResult();
2667 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462668 TestNetLogEntry::List entries;
ttuttle34f63b52015-03-05 04:33:012669 log.GetEntries(&entries);
2670 size_t pos = ExpectLogContainsSomewhere(
2671 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2672 NetLog::PHASE_NONE);
2673 ExpectLogContainsSomewhere(
2674 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2675 NetLog::PHASE_NONE);
2676
2677 const HttpResponseInfo* response = trans->GetResponseInfo();
2678 ASSERT_TRUE(response != NULL);
2679 EXPECT_FALSE(response->headers->IsKeepAlive());
2680 ASSERT_FALSE(response->headers.get() == NULL);
2681 EXPECT_EQ(407, response->headers->response_code());
2682 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2683 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2684
2685 LoadTimingInfo load_timing_info;
2686 // CONNECT requests and responses are handled at the connect job level, so
2687 // the transaction does not yet have a connection.
2688 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2689
2690 TestCompletionCallback callback2;
2691
2692 rv =
2693 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
2694 EXPECT_EQ(ERR_IO_PENDING, rv);
2695
2696 rv = callback2.WaitForResult();
2697 EXPECT_EQ(OK, rv);
2698
2699 response = trans->GetResponseInfo();
2700 ASSERT_TRUE(response != NULL);
2701
2702 EXPECT_TRUE(response->headers->IsKeepAlive());
2703 EXPECT_EQ(200, response->headers->response_code());
2704 EXPECT_EQ(5, response->headers->GetContentLength());
2705 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2706
2707 // The password prompt info should not be set.
2708 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2709
2710 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2711 TestLoadTimingNotReusedWithPac(load_timing_info,
2712 CONNECT_TIMING_HAS_SSL_TIMES);
2713
2714 trans.reset();
2715 session->CloseAllConnections();
2716}
2717
2718// Test the request-challenge-retry sequence for basic auth, over a connection
2719// that requires a restart when setting up an SSL tunnel.
2720TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:592721 HttpRequestInfo request;
2722 request.method = "GET";
bncce36dca22015-04-21 22:11:232723 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:592724 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292725 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]394816e92010-08-03 07:38:592726
[email protected]cb9bf6ca2011-01-28 13:15:272727 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032728 session_deps_.proxy_service =
2729 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512730 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072731 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:422732 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272733
[email protected]394816e92010-08-03 07:38:592734 // Since we have proxy, should try to establish tunnel.
2735 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542736 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172737 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542738 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:112739 };
2740
mmenkee71e15332015-10-07 16:39:542741 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:082742 // connection.
2743 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:542744 // No credentials.
2745 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2746 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2747 MockRead("Proxy-Connection: close\r\n\r\n"),
2748 };
mmenkee0b5c882015-08-26 20:29:112749
mmenkee71e15332015-10-07 16:39:542750 MockWrite data_writes2[] = {
2751 // After calling trans->RestartWithAuth(), this is the request we should
2752 // be issuing -- the final header line contains the credentials.
2753 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172754 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542755 "Proxy-Connection: keep-alive\r\n"
2756 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:082757
mmenkee71e15332015-10-07 16:39:542758 MockWrite("GET / HTTP/1.1\r\n"
2759 "Host: www.example.org\r\n"
2760 "Connection: keep-alive\r\n\r\n"),
2761 };
2762
2763 MockRead data_reads2[] = {
2764 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2765
2766 MockRead("HTTP/1.1 200 OK\r\n"),
2767 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2768 MockRead("Content-Length: 5\r\n\r\n"),
2769 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:592770 };
2771
2772 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2773 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:072774 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542775 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2776 data_writes2, arraysize(data_writes2));
2777 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:062778 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:072779 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:592780
[email protected]49639fa2011-12-20 23:22:412781 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:592782
[email protected]262eec82013-03-19 21:01:362783 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502784 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:502785
[email protected]49639fa2011-12-20 23:22:412786 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]394816e92010-08-03 07:38:592787 EXPECT_EQ(ERR_IO_PENDING, rv);
2788
2789 rv = callback1.WaitForResult();
2790 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:462791 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:402792 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:592793 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402794 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:592795 NetLog::PHASE_NONE);
2796 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402797 entries, pos,
[email protected]394816e92010-08-03 07:38:592798 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2799 NetLog::PHASE_NONE);
2800
2801 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502802 ASSERT_TRUE(response != NULL);
ttuttle34f63b52015-03-05 04:33:012803 EXPECT_FALSE(response->headers->IsKeepAlive());
[email protected]90499482013-06-01 00:39:502804 ASSERT_FALSE(response->headers.get() == NULL);
[email protected]394816e92010-08-03 07:38:592805 EXPECT_EQ(407, response->headers->response_code());
2806 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042807 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]394816e92010-08-03 07:38:592808
[email protected]029c83b62013-01-24 05:28:202809 LoadTimingInfo load_timing_info;
2810 // CONNECT requests and responses are handled at the connect job level, so
2811 // the transaction does not yet have a connection.
2812 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2813
[email protected]49639fa2011-12-20 23:22:412814 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:592815
[email protected]49639fa2011-12-20 23:22:412816 rv = trans->RestartWithAuth(
2817 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]394816e92010-08-03 07:38:592818 EXPECT_EQ(ERR_IO_PENDING, rv);
2819
2820 rv = callback2.WaitForResult();
2821 EXPECT_EQ(OK, rv);
2822
2823 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502824 ASSERT_TRUE(response != NULL);
[email protected]394816e92010-08-03 07:38:592825
2826 EXPECT_TRUE(response->headers->IsKeepAlive());
2827 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:502828 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:592829 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2830
2831 // The password prompt info should not be set.
2832 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:502833
[email protected]029c83b62013-01-24 05:28:202834 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2835 TestLoadTimingNotReusedWithPac(load_timing_info,
2836 CONNECT_TIMING_HAS_SSL_TIMES);
2837
[email protected]0b0bf032010-09-21 18:08:502838 trans.reset();
[email protected]102e27c2011-02-23 01:01:312839 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:592840}
2841
[email protected]11203f012009-11-12 23:02:312842// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:012843// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2844TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:232845 // On the second pass, the body read of the auth challenge is synchronous, so
2846 // IsConnectedAndIdle returns false. The socket should still be drained and
2847 // reused. See http://crbug.com/544255.
2848 for (int i = 0; i < 2; ++i) {
2849 HttpRequestInfo request;
2850 request.method = "GET";
2851 request.url = GURL("https://www.example.org/");
2852 // Ensure that proxy authentication is attempted even
2853 // when the no authentication data flag is set.
2854 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:012855
mmenked39192ee2015-12-09 00:57:232856 // Configure against proxy server "myproxy:70".
2857 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
2858 BoundTestNetLog log;
2859 session_deps_.net_log = log.bound().net_log();
2860 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:012861
mmenked39192ee2015-12-09 00:57:232862 scoped_ptr<HttpTransaction> trans(
2863 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
ttuttle34f63b52015-03-05 04:33:012864
mmenked39192ee2015-12-09 00:57:232865 // Since we have proxy, should try to establish tunnel.
2866 MockWrite data_writes1[] = {
2867 MockWrite(ASYNC, 0,
2868 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2869 "Host: www.example.org:443\r\n"
2870 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:012871
mmenked39192ee2015-12-09 00:57:232872 // After calling trans->RestartWithAuth(), this is the request we should
2873 // be issuing -- the final header line contains the credentials.
2874 MockWrite(ASYNC, 3,
2875 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2876 "Host: www.example.org:443\r\n"
2877 "Proxy-Connection: keep-alive\r\n"
2878 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2879 };
ttuttle34f63b52015-03-05 04:33:012880
mmenked39192ee2015-12-09 00:57:232881 // The proxy responds to the connect with a 407, using a persistent
2882 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2883 MockRead data_reads1[] = {
2884 // No credentials.
2885 MockRead(ASYNC, 1,
2886 "HTTP/1.0 407 Proxy Authentication Required\r\n"
2887 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
2888 "Proxy-Connection: keep-alive\r\n"
2889 "Content-Length: 10\r\n\r\n"),
2890 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:012891
mmenked39192ee2015-12-09 00:57:232892 // Wrong credentials (wrong password).
2893 MockRead(ASYNC, 4,
2894 "HTTP/1.0 407 Proxy Authentication Required\r\n"
2895 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
2896 "Proxy-Connection: keep-alive\r\n"
2897 "Content-Length: 10\r\n\r\n"),
2898 // No response body because the test stops reading here.
2899 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
2900 };
ttuttle34f63b52015-03-05 04:33:012901
mmenked39192ee2015-12-09 00:57:232902 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
2903 arraysize(data_writes1));
2904 data1.set_busy_before_sync_reads(true);
2905 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:012906
mmenked39192ee2015-12-09 00:57:232907 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:012908
mmenked39192ee2015-12-09 00:57:232909 int rv = trans->Start(&request, callback1.callback(), log.bound());
2910 EXPECT_EQ(OK, callback1.GetResult(rv));
ttuttle34f63b52015-03-05 04:33:012911
mmenked39192ee2015-12-09 00:57:232912 TestNetLogEntry::List entries;
2913 log.GetEntries(&entries);
2914 size_t pos = ExpectLogContainsSomewhere(
2915 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2916 NetLog::PHASE_NONE);
2917 ExpectLogContainsSomewhere(
2918 entries, pos,
2919 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2920 NetLog::PHASE_NONE);
ttuttle34f63b52015-03-05 04:33:012921
mmenked39192ee2015-12-09 00:57:232922 const HttpResponseInfo* response = trans->GetResponseInfo();
2923 ASSERT_TRUE(response);
2924 ASSERT_TRUE(response->headers);
2925 EXPECT_TRUE(response->headers->IsKeepAlive());
2926 EXPECT_EQ(407, response->headers->response_code());
2927 EXPECT_EQ(10, response->headers->GetContentLength());
2928 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2929 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
ttuttle34f63b52015-03-05 04:33:012930
mmenked39192ee2015-12-09 00:57:232931 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:012932
mmenked39192ee2015-12-09 00:57:232933 // Wrong password (should be "bar").
2934 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBaz),
2935 callback2.callback());
2936 EXPECT_EQ(OK, callback2.GetResult(rv));
ttuttle34f63b52015-03-05 04:33:012937
mmenked39192ee2015-12-09 00:57:232938 response = trans->GetResponseInfo();
2939 ASSERT_TRUE(response);
2940 ASSERT_TRUE(response->headers);
2941 EXPECT_TRUE(response->headers->IsKeepAlive());
2942 EXPECT_EQ(407, response->headers->response_code());
2943 EXPECT_EQ(10, response->headers->GetContentLength());
2944 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2945 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
ttuttle34f63b52015-03-05 04:33:012946
mmenked39192ee2015-12-09 00:57:232947 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2948 // out of scope.
2949 session->CloseAllConnections();
2950 }
ttuttle34f63b52015-03-05 04:33:012951}
2952
2953// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2954// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2955TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:232956 // On the second pass, the body read of the auth challenge is synchronous, so
2957 // IsConnectedAndIdle returns false. The socket should still be drained and
2958 // reused. See http://crbug.com/544255.
2959 for (int i = 0; i < 2; ++i) {
2960 HttpRequestInfo request;
2961 request.method = "GET";
2962 request.url = GURL("https://www.example.org/");
2963 // Ensure that proxy authentication is attempted even
2964 // when the no authentication data flag is set.
2965 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
2966
2967 // Configure against proxy server "myproxy:70".
2968 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
2969 BoundTestNetLog log;
2970 session_deps_.net_log = log.bound().net_log();
2971 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2972
2973 scoped_ptr<HttpTransaction> trans(
2974 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2975
2976 // Since we have proxy, should try to establish tunnel.
2977 MockWrite data_writes1[] = {
2978 MockWrite(ASYNC, 0,
2979 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2980 "Host: www.example.org:443\r\n"
2981 "Proxy-Connection: keep-alive\r\n\r\n"),
2982
2983 // After calling trans->RestartWithAuth(), this is the request we should
2984 // be issuing -- the final header line contains the credentials.
2985 MockWrite(ASYNC, 3,
2986 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2987 "Host: www.example.org:443\r\n"
2988 "Proxy-Connection: keep-alive\r\n"
2989 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2990 };
2991
2992 // The proxy responds to the connect with a 407, using a persistent
2993 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2994 MockRead data_reads1[] = {
2995 // No credentials.
2996 MockRead(ASYNC, 1,
2997 "HTTP/1.1 407 Proxy Authentication Required\r\n"
2998 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
2999 "Content-Length: 10\r\n\r\n"),
3000 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3001
3002 // Wrong credentials (wrong password).
3003 MockRead(ASYNC, 4,
3004 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3005 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3006 "Content-Length: 10\r\n\r\n"),
3007 // No response body because the test stops reading here.
3008 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3009 };
3010
3011 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
3012 arraysize(data_writes1));
3013 data1.set_busy_before_sync_reads(true);
3014 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3015
3016 TestCompletionCallback callback1;
3017
3018 int rv = trans->Start(&request, callback1.callback(), log.bound());
3019 EXPECT_EQ(OK, callback1.GetResult(rv));
3020
3021 TestNetLogEntry::List entries;
3022 log.GetEntries(&entries);
3023 size_t pos = ExpectLogContainsSomewhere(
3024 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3025 NetLog::PHASE_NONE);
3026 ExpectLogContainsSomewhere(
3027 entries, pos,
3028 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3029 NetLog::PHASE_NONE);
3030
3031 const HttpResponseInfo* response = trans->GetResponseInfo();
3032 ASSERT_TRUE(response);
3033 ASSERT_TRUE(response->headers);
3034 EXPECT_TRUE(response->headers->IsKeepAlive());
3035 EXPECT_EQ(407, response->headers->response_code());
3036 EXPECT_EQ(10, response->headers->GetContentLength());
3037 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3038 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3039
3040 TestCompletionCallback callback2;
3041
3042 // Wrong password (should be "bar").
3043 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBaz),
3044 callback2.callback());
3045 EXPECT_EQ(OK, callback2.GetResult(rv));
3046
3047 response = trans->GetResponseInfo();
3048 ASSERT_TRUE(response);
3049 ASSERT_TRUE(response->headers);
3050 EXPECT_TRUE(response->headers->IsKeepAlive());
3051 EXPECT_EQ(407, response->headers->response_code());
3052 EXPECT_EQ(10, response->headers->GetContentLength());
3053 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3054 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3055
3056 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3057 // out of scope.
3058 session->CloseAllConnections();
3059 }
3060}
3061
3062// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3063// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3064// the case the server sends extra data on the original socket, so it can't be
3065// reused.
3066TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273067 HttpRequestInfo request;
3068 request.method = "GET";
bncce36dca22015-04-21 22:11:233069 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273070 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293071 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]cb9bf6ca2011-01-28 13:15:273072
[email protected]2d2697f92009-02-18 21:00:323073 // Configure against proxy server "myproxy:70".
mmenked39192ee2015-12-09 00:57:233074 session_deps_.proxy_service =
3075 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:513076 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073077 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423078 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323079
[email protected]2d2697f92009-02-18 21:00:323080 // Since we have proxy, should try to establish tunnel.
3081 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233082 MockWrite(ASYNC, 0,
3083 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173084 "Host: www.example.org:443\r\n"
3085 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233086 };
[email protected]2d2697f92009-02-18 21:00:323087
mmenked39192ee2015-12-09 00:57:233088 // The proxy responds to the connect with a 407, using a persistent, but sends
3089 // extra data, so the socket cannot be reused.
3090 MockRead data_reads1[] = {
3091 // No credentials.
3092 MockRead(ASYNC, 1,
3093 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3094 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3095 "Content-Length: 10\r\n\r\n"),
3096 MockRead(SYNCHRONOUS, 2, "0123456789"),
3097 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3098 };
3099
3100 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233101 // After calling trans->RestartWithAuth(), this is the request we should
3102 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233103 MockWrite(ASYNC, 0,
3104 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173105 "Host: www.example.org:443\r\n"
3106 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233107 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3108
3109 MockWrite(ASYNC, 2,
3110 "GET / HTTP/1.1\r\n"
3111 "Host: www.example.org\r\n"
3112 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323113 };
3114
mmenked39192ee2015-12-09 00:57:233115 MockRead data_reads2[] = {
3116 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323117
mmenked39192ee2015-12-09 00:57:233118 MockRead(ASYNC, 3,
3119 "HTTP/1.1 200 OK\r\n"
3120 "Content-Type: text/html; charset=iso-8859-1\r\n"
3121 "Content-Length: 5\r\n\r\n"),
3122 // No response body because the test stops reading here.
3123 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323124 };
3125
mmenked39192ee2015-12-09 00:57:233126 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
3127 arraysize(data_writes1));
3128 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073129 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenked39192ee2015-12-09 00:57:233130 SequencedSocketData data2(data_reads2, arraysize(data_reads2), data_writes2,
3131 arraysize(data_writes2));
3132 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3133 SSLSocketDataProvider ssl(ASYNC, OK);
3134 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323135
[email protected]49639fa2011-12-20 23:22:413136 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323137
mmenked39192ee2015-12-09 00:57:233138 scoped_ptr<HttpTransaction> trans(
3139 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d2697f92009-02-18 21:00:323140
mmenked39192ee2015-12-09 00:57:233141 int rv = trans->Start(&request, callback1.callback(), log.bound());
3142 EXPECT_EQ(OK, callback1.GetResult(rv));
3143
mmenke43758e62015-05-04 21:09:463144 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403145 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:393146 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403147 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:393148 NetLog::PHASE_NONE);
3149 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403150 entries, pos,
[email protected]dbb83db2010-05-11 18:13:393151 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3152 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:323153
[email protected]1c773ea12009-04-28 19:58:423154 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243155 ASSERT_TRUE(response);
3156 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323157 EXPECT_TRUE(response->headers->IsKeepAlive());
3158 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423159 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:043160 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:323161
mmenked39192ee2015-12-09 00:57:233162 LoadTimingInfo load_timing_info;
3163 // CONNECT requests and responses are handled at the connect job level, so
3164 // the transaction does not yet have a connection.
3165 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3166
[email protected]49639fa2011-12-20 23:22:413167 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323168
mmenked39192ee2015-12-09 00:57:233169 rv =
3170 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
3171 EXPECT_EQ(OK, callback2.GetResult(rv));
[email protected]2d2697f92009-02-18 21:00:323172
[email protected]2d2697f92009-02-18 21:00:323173 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233174 EXPECT_EQ(200, response->headers->response_code());
3175 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423176 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133177
mmenked39192ee2015-12-09 00:57:233178 // The password prompt info should not be set.
3179 EXPECT_FALSE(response->auth_challenge);
3180
3181 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3182 TestLoadTimingNotReusedWithPac(load_timing_info,
3183 CONNECT_TIMING_HAS_SSL_TIMES);
3184
3185 trans.reset();
[email protected]102e27c2011-02-23 01:01:313186 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323187}
3188
mmenkee71e15332015-10-07 16:39:543189// Test the case a proxy closes a socket while the challenge body is being
3190// drained.
3191TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
3192 HttpRequestInfo request;
3193 request.method = "GET";
3194 request.url = GURL("https://www.example.org/");
3195 // Ensure that proxy authentication is attempted even
3196 // when the no authentication data flag is set.
3197 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
3198
3199 // Configure against proxy server "myproxy:70".
3200 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:423201 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543202
3203 scoped_ptr<HttpTransaction> trans(
3204 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3205
3206 // Since we have proxy, should try to establish tunnel.
3207 MockWrite data_writes1[] = {
3208 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173209 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543210 "Proxy-Connection: keep-alive\r\n\r\n"),
3211 };
3212
3213 // The proxy responds to the connect with a 407, using a persistent
3214 // connection.
3215 MockRead data_reads1[] = {
3216 // No credentials.
3217 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3218 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3219 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3220 // Server hands up in the middle of the body.
3221 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3222 };
3223
3224 MockWrite data_writes2[] = {
3225 // After calling trans->RestartWithAuth(), this is the request we should
3226 // be issuing -- the final header line contains the credentials.
3227 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173228 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543229 "Proxy-Connection: keep-alive\r\n"
3230 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3231
3232 MockWrite("GET / HTTP/1.1\r\n"
3233 "Host: www.example.org\r\n"
3234 "Connection: keep-alive\r\n\r\n"),
3235 };
3236
3237 MockRead data_reads2[] = {
3238 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3239
3240 MockRead("HTTP/1.1 200 OK\r\n"),
3241 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3242 MockRead("Content-Length: 5\r\n\r\n"),
3243 MockRead(SYNCHRONOUS, "hello"),
3244 };
3245
3246 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3247 data_writes1, arraysize(data_writes1));
3248 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3249 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3250 data_writes2, arraysize(data_writes2));
3251 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3252 SSLSocketDataProvider ssl(ASYNC, OK);
3253 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3254
3255 TestCompletionCallback callback;
3256
3257 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3258 EXPECT_EQ(OK, callback.GetResult(rv));
3259
3260 const HttpResponseInfo* response = trans->GetResponseInfo();
3261 ASSERT_TRUE(response);
3262 ASSERT_TRUE(response->headers);
3263 EXPECT_TRUE(response->headers->IsKeepAlive());
3264 EXPECT_EQ(407, response->headers->response_code());
3265 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3266
3267 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
3268 EXPECT_EQ(OK, callback.GetResult(rv));
3269
3270 response = trans->GetResponseInfo();
3271 ASSERT_TRUE(response);
3272 ASSERT_TRUE(response->headers);
3273 EXPECT_TRUE(response->headers->IsKeepAlive());
3274 EXPECT_EQ(200, response->headers->response_code());
3275 std::string body;
3276 EXPECT_EQ(OK, ReadTransaction(trans.get(), &body));
3277 EXPECT_EQ("hello", body);
3278}
3279
[email protected]a8e9b162009-03-12 00:06:443280// Test that we don't read the response body when we fail to establish a tunnel,
3281// even if the user cancels the proxy's auth attempt.
[email protected]23e482282013-06-14 16:08:023282TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273283 HttpRequestInfo request;
3284 request.method = "GET";
bncce36dca22015-04-21 22:11:233285 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273286 request.load_flags = 0;
3287
[email protected]a8e9b162009-03-12 00:06:443288 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033289 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]a8e9b162009-03-12 00:06:443290
mmenkee65e7af2015-10-13 17:16:423291 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443292
[email protected]262eec82013-03-19 21:01:363293 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503294 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]a8e9b162009-03-12 00:06:443295
[email protected]a8e9b162009-03-12 00:06:443296 // Since we have proxy, should try to establish tunnel.
3297 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173298 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3299 "Host: www.example.org:443\r\n"
3300 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443301 };
3302
3303 // The proxy responds to the connect with a 407.
3304 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243305 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3306 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3307 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233308 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:243309 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443310 };
3311
[email protected]31a2bfe2010-02-09 08:03:393312 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3313 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:073314 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443315
[email protected]49639fa2011-12-20 23:22:413316 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443317
[email protected]49639fa2011-12-20 23:22:413318 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423319 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:443320
3321 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423322 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:443323
[email protected]1c773ea12009-04-28 19:58:423324 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243325 ASSERT_TRUE(response);
3326 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:443327 EXPECT_TRUE(response->headers->IsKeepAlive());
3328 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423329 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:443330
3331 std::string response_data;
3332 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423333 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:183334
3335 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:313336 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:443337}
3338
ttuttle7933c112015-01-06 00:55:243339// Test that we don't pass extraneous headers from the proxy's response to the
3340// caller when the proxy responds to CONNECT with 407.
3341TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
3342 HttpRequestInfo request;
3343 request.method = "GET";
bncce36dca22015-04-21 22:11:233344 request.url = GURL("https://www.example.org/");
ttuttle7933c112015-01-06 00:55:243345 request.load_flags = 0;
3346
3347 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033348 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
ttuttle7933c112015-01-06 00:55:243349
mmenkee65e7af2015-10-13 17:16:423350 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:243351
3352 scoped_ptr<HttpTransaction> trans(
3353 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3354
3355 // Since we have proxy, should try to establish tunnel.
3356 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173357 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3358 "Host: www.example.org:443\r\n"
3359 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:243360 };
3361
3362 // The proxy responds to the connect with a 407.
3363 MockRead data_reads[] = {
3364 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3365 MockRead("X-Foo: bar\r\n"),
3366 MockRead("Set-Cookie: foo=bar\r\n"),
3367 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3368 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233369 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:243370 };
3371
3372 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
3373 arraysize(data_writes));
3374 session_deps_.socket_factory->AddSocketDataProvider(&data);
3375
3376 TestCompletionCallback callback;
3377
3378 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3379 EXPECT_EQ(ERR_IO_PENDING, rv);
3380
3381 rv = callback.WaitForResult();
3382 EXPECT_EQ(OK, rv);
3383
3384 const HttpResponseInfo* response = trans->GetResponseInfo();
3385 ASSERT_TRUE(response);
3386 ASSERT_TRUE(response->headers);
3387 EXPECT_TRUE(response->headers->IsKeepAlive());
3388 EXPECT_EQ(407, response->headers->response_code());
3389 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3390 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
3391 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
3392
3393 std::string response_data;
3394 rv = ReadTransaction(trans.get(), &response_data);
3395 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3396
3397 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3398 session->CloseAllConnections();
3399}
3400
[email protected]8fdbcd22010-05-05 02:54:523401// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
3402// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
[email protected]23e482282013-06-14 16:08:023403TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:523404 HttpRequestInfo request;
3405 request.method = "GET";
bncce36dca22015-04-21 22:11:233406 request.url = GURL("http://www.example.org/");
[email protected]8fdbcd22010-05-05 02:54:523407 request.load_flags = 0;
3408
[email protected]cb9bf6ca2011-01-28 13:15:273409 // We are using a DIRECT connection (i.e. no proxy) for this session.
mmenkee65e7af2015-10-13 17:16:423410 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273411 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:413412 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:273413
[email protected]8fdbcd22010-05-05 02:54:523414 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233415 MockWrite(
3416 "GET / HTTP/1.1\r\n"
3417 "Host: www.example.org\r\n"
3418 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:523419 };
3420
3421 MockRead data_reads1[] = {
3422 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
3423 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3424 // Large content-length -- won't matter, as connection will be reset.
3425 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063426 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:523427 };
3428
3429 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3430 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073431 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:523432
[email protected]49639fa2011-12-20 23:22:413433 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:523434
[email protected]49639fa2011-12-20 23:22:413435 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]8fdbcd22010-05-05 02:54:523436 EXPECT_EQ(ERR_IO_PENDING, rv);
3437
3438 rv = callback.WaitForResult();
3439 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
3440}
3441
[email protected]7a67a8152010-11-05 18:31:103442// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3443// through a non-authenticating proxy. The request should fail with
3444// ERR_UNEXPECTED_PROXY_AUTH.
3445// Note that it is impossible to detect if an HTTP server returns a 407 through
3446// a non-authenticating proxy - there is nothing to indicate whether the
3447// response came from the proxy or the server, so it is treated as if the proxy
3448// issued the challenge.
[email protected]23e482282013-06-14 16:08:023449TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:233450 HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:273451 HttpRequestInfo request;
3452 request.method = "GET";
bncce36dca22015-04-21 22:11:233453 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273454
rdsmith82957ad2015-09-16 19:42:033455 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:513456 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073457 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423458 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:103459
[email protected]7a67a8152010-11-05 18:31:103460 // Since we have proxy, should try to establish tunnel.
3461 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:173462 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3463 "Host: www.example.org:443\r\n"
3464 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103465
rsleevidb16bb02015-11-12 23:47:173466 MockWrite("GET / HTTP/1.1\r\n"
3467 "Host: www.example.org\r\n"
3468 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103469 };
3470
3471 MockRead data_reads1[] = {
3472 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3473
3474 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3475 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3476 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:063477 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:103478 };
3479
3480 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3481 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073482 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:063483 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073484 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:103485
[email protected]49639fa2011-12-20 23:22:413486 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:103487
[email protected]262eec82013-03-19 21:01:363488 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503489 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a67a8152010-11-05 18:31:103490
[email protected]49639fa2011-12-20 23:22:413491 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7a67a8152010-11-05 18:31:103492 EXPECT_EQ(ERR_IO_PENDING, rv);
3493
3494 rv = callback1.WaitForResult();
3495 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
mmenke43758e62015-05-04 21:09:463496 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403497 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:103498 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403499 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:103500 NetLog::PHASE_NONE);
3501 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403502 entries, pos,
[email protected]7a67a8152010-11-05 18:31:103503 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3504 NetLog::PHASE_NONE);
3505}
[email protected]2df19bb2010-08-25 20:13:463506
mmenke2a1781d2015-10-07 19:25:333507// Test a proxy auth scheme that allows default credentials and a proxy server
3508// that uses non-persistent connections.
3509TEST_P(HttpNetworkTransactionTest,
3510 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
3511 HttpRequestInfo request;
3512 request.method = "GET";
3513 request.url = GURL("https://www.example.org/");
3514
3515 // Configure against proxy server "myproxy:70".
3516 session_deps_.proxy_service =
3517 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3518
3519 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3520 new HttpAuthHandlerMock::Factory());
3521 auth_handler_factory->set_do_init_from_challenge(true);
3522 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3523 mock_handler->set_allows_default_credentials(true);
3524 auth_handler_factory->AddMockHandler(mock_handler.release(),
3525 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483526 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333527
3528 // Add NetLog just so can verify load timing information gets a NetLog ID.
3529 NetLog net_log;
3530 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423531 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333532
3533 // Since we have proxy, should try to establish tunnel.
3534 MockWrite data_writes1[] = {
3535 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173536 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333537 "Proxy-Connection: keep-alive\r\n\r\n"),
3538 };
3539
3540 // The proxy responds to the connect with a 407, using a non-persistent
3541 // connection.
3542 MockRead data_reads1[] = {
3543 // No credentials.
3544 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3545 MockRead("Proxy-Authenticate: Mock\r\n"),
3546 MockRead("Proxy-Connection: close\r\n\r\n"),
3547 };
3548
3549 // Since the first connection couldn't be reused, need to establish another
3550 // once given credentials.
3551 MockWrite data_writes2[] = {
3552 // After calling trans->RestartWithAuth(), this is the request we should
3553 // be issuing -- the final header line contains the credentials.
3554 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173555 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333556 "Proxy-Connection: keep-alive\r\n"
3557 "Proxy-Authorization: auth_token\r\n\r\n"),
3558
3559 MockWrite("GET / HTTP/1.1\r\n"
3560 "Host: www.example.org\r\n"
3561 "Connection: keep-alive\r\n\r\n"),
3562 };
3563
3564 MockRead data_reads2[] = {
3565 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3566
3567 MockRead("HTTP/1.1 200 OK\r\n"),
3568 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3569 MockRead("Content-Length: 5\r\n\r\n"),
3570 MockRead(SYNCHRONOUS, "hello"),
3571 };
3572
3573 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3574 data_writes1, arraysize(data_writes1));
3575 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3576 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3577 data_writes2, arraysize(data_writes2));
3578 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3579 SSLSocketDataProvider ssl(ASYNC, OK);
3580 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3581
3582 scoped_ptr<HttpTransaction> trans(
3583 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3584
3585 TestCompletionCallback callback;
3586 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3587 EXPECT_EQ(OK, callback.GetResult(rv));
3588
3589 const HttpResponseInfo* response = trans->GetResponseInfo();
3590 ASSERT_TRUE(response);
3591 ASSERT_TRUE(response->headers);
3592 EXPECT_FALSE(response->headers->IsKeepAlive());
3593 EXPECT_EQ(407, response->headers->response_code());
3594 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3595 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3596 EXPECT_FALSE(response->auth_challenge.get());
3597
3598 LoadTimingInfo load_timing_info;
3599 // CONNECT requests and responses are handled at the connect job level, so
3600 // the transaction does not yet have a connection.
3601 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3602
3603 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3604 EXPECT_EQ(OK, callback.GetResult(rv));
3605 response = trans->GetResponseInfo();
3606 ASSERT_TRUE(response);
3607 ASSERT_TRUE(response->headers);
3608 EXPECT_TRUE(response->headers->IsKeepAlive());
3609 EXPECT_EQ(200, response->headers->response_code());
3610 EXPECT_EQ(5, response->headers->GetContentLength());
3611 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3612
3613 // The password prompt info should not be set.
3614 EXPECT_FALSE(response->auth_challenge);
3615
3616 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3617 TestLoadTimingNotReusedWithPac(load_timing_info,
3618 CONNECT_TIMING_HAS_SSL_TIMES);
3619
3620 trans.reset();
3621 session->CloseAllConnections();
3622}
3623
3624// Test a proxy auth scheme that allows default credentials and a proxy server
3625// that hangs up when credentials are initially sent.
3626TEST_P(HttpNetworkTransactionTest,
3627 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
3628 HttpRequestInfo request;
3629 request.method = "GET";
3630 request.url = GURL("https://www.example.org/");
3631
3632 // Configure against proxy server "myproxy:70".
3633 session_deps_.proxy_service =
3634 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3635
3636 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3637 new HttpAuthHandlerMock::Factory());
3638 auth_handler_factory->set_do_init_from_challenge(true);
3639 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3640 mock_handler->set_allows_default_credentials(true);
3641 auth_handler_factory->AddMockHandler(mock_handler.release(),
3642 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483643 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333644
3645 // Add NetLog just so can verify load timing information gets a NetLog ID.
3646 NetLog net_log;
3647 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423648 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333649
3650 // Should try to establish tunnel.
3651 MockWrite data_writes1[] = {
3652 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173653 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333654 "Proxy-Connection: keep-alive\r\n\r\n"),
3655
3656 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173657 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333658 "Proxy-Connection: keep-alive\r\n"
3659 "Proxy-Authorization: auth_token\r\n\r\n"),
3660 };
3661
3662 // The proxy responds to the connect with a 407, using a non-persistent
3663 // connection.
3664 MockRead data_reads1[] = {
3665 // No credentials.
3666 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3667 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3668 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3669 };
3670
3671 // Since the first connection was closed, need to establish another once given
3672 // credentials.
3673 MockWrite data_writes2[] = {
3674 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173675 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333676 "Proxy-Connection: keep-alive\r\n"
3677 "Proxy-Authorization: auth_token\r\n\r\n"),
3678
3679 MockWrite("GET / HTTP/1.1\r\n"
3680 "Host: www.example.org\r\n"
3681 "Connection: keep-alive\r\n\r\n"),
3682 };
3683
3684 MockRead data_reads2[] = {
3685 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3686
3687 MockRead("HTTP/1.1 200 OK\r\n"),
3688 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3689 MockRead("Content-Length: 5\r\n\r\n"),
3690 MockRead(SYNCHRONOUS, "hello"),
3691 };
3692
3693 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3694 data_writes1, arraysize(data_writes1));
3695 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3696 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3697 data_writes2, arraysize(data_writes2));
3698 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3699 SSLSocketDataProvider ssl(ASYNC, OK);
3700 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3701
3702 scoped_ptr<HttpTransaction> trans(
3703 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3704
3705 TestCompletionCallback callback;
3706 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3707 EXPECT_EQ(OK, callback.GetResult(rv));
3708
3709 const HttpResponseInfo* response = trans->GetResponseInfo();
3710 ASSERT_TRUE(response);
3711 ASSERT_TRUE(response->headers);
3712 EXPECT_TRUE(response->headers->IsKeepAlive());
3713 EXPECT_EQ(407, response->headers->response_code());
3714 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3715 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3716 EXPECT_FALSE(response->auth_challenge);
3717
3718 LoadTimingInfo load_timing_info;
3719 // CONNECT requests and responses are handled at the connect job level, so
3720 // the transaction does not yet have a connection.
3721 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3722
3723 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3724 EXPECT_EQ(OK, callback.GetResult(rv));
3725
3726 response = trans->GetResponseInfo();
3727 ASSERT_TRUE(response);
3728 ASSERT_TRUE(response->headers);
3729 EXPECT_TRUE(response->headers->IsKeepAlive());
3730 EXPECT_EQ(200, response->headers->response_code());
3731 EXPECT_EQ(5, response->headers->GetContentLength());
3732 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3733
3734 // The password prompt info should not be set.
3735 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3736
3737 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3738 TestLoadTimingNotReusedWithPac(load_timing_info,
3739 CONNECT_TIMING_HAS_SSL_TIMES);
3740
3741 trans.reset();
3742 session->CloseAllConnections();
3743}
3744
3745// Test a proxy auth scheme that allows default credentials and a proxy server
3746// that hangs up when credentials are initially sent, and hangs up again when
3747// they are retried.
3748TEST_P(HttpNetworkTransactionTest,
3749 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
3750 HttpRequestInfo request;
3751 request.method = "GET";
3752 request.url = GURL("https://www.example.org/");
3753
3754 // Configure against proxy server "myproxy:70".
3755 session_deps_.proxy_service =
3756 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3757
3758 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3759 new HttpAuthHandlerMock::Factory());
3760 auth_handler_factory->set_do_init_from_challenge(true);
3761 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3762 mock_handler->set_allows_default_credentials(true);
3763 auth_handler_factory->AddMockHandler(mock_handler.release(),
3764 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483765 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333766
3767 // Add NetLog just so can verify load timing information gets a NetLog ID.
3768 NetLog net_log;
3769 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423770 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333771
3772 // Should try to establish tunnel.
3773 MockWrite data_writes1[] = {
3774 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173775 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333776 "Proxy-Connection: keep-alive\r\n\r\n"),
3777
3778 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173779 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333780 "Proxy-Connection: keep-alive\r\n"
3781 "Proxy-Authorization: auth_token\r\n\r\n"),
3782 };
3783
3784 // The proxy responds to the connect with a 407, and then hangs up after the
3785 // second request is sent.
3786 MockRead data_reads1[] = {
3787 // No credentials.
3788 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3789 MockRead("Content-Length: 0\r\n"),
3790 MockRead("Proxy-Connection: keep-alive\r\n"),
3791 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3792 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3793 };
3794
3795 // HttpNetworkTransaction sees a reused connection that was closed with
3796 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
3797 // request.
3798 MockWrite data_writes2[] = {
3799 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173800 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333801 "Proxy-Connection: keep-alive\r\n\r\n"),
3802 };
3803
3804 // The proxy, having had more than enough of us, just hangs up.
3805 MockRead data_reads2[] = {
3806 // No credentials.
3807 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3808 };
3809
3810 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3811 data_writes1, arraysize(data_writes1));
3812 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3813 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3814 data_writes2, arraysize(data_writes2));
3815 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3816
3817 scoped_ptr<HttpTransaction> trans(
3818 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3819
3820 TestCompletionCallback callback;
3821 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3822 EXPECT_EQ(OK, callback.GetResult(rv));
3823
3824 const HttpResponseInfo* response = trans->GetResponseInfo();
3825 ASSERT_TRUE(response);
3826 ASSERT_TRUE(response->headers);
3827 EXPECT_TRUE(response->headers->IsKeepAlive());
3828 EXPECT_EQ(407, response->headers->response_code());
3829 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3830 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3831 EXPECT_FALSE(response->auth_challenge);
3832
3833 LoadTimingInfo load_timing_info;
3834 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3835
3836 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3837 EXPECT_EQ(ERR_EMPTY_RESPONSE, callback.GetResult(rv));
3838
3839 trans.reset();
3840 session->CloseAllConnections();
3841}
3842
3843// Test a proxy auth scheme that allows default credentials and a proxy server
3844// that hangs up when credentials are initially sent, and sends a challenge
3845// again they are retried.
3846TEST_P(HttpNetworkTransactionTest,
3847 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
3848 HttpRequestInfo request;
3849 request.method = "GET";
3850 request.url = GURL("https://www.example.org/");
3851
3852 // Configure against proxy server "myproxy:70".
3853 session_deps_.proxy_service =
3854 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3855
3856 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
3857 new HttpAuthHandlerMock::Factory());
3858 auth_handler_factory->set_do_init_from_challenge(true);
3859 scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
3860 mock_handler->set_allows_default_credentials(true);
3861 auth_handler_factory->AddMockHandler(mock_handler.release(),
3862 HttpAuth::AUTH_PROXY);
3863 // Add another handler for the second challenge. It supports default
3864 // credentials, but they shouldn't be used, since they were already tried.
3865 mock_handler.reset(new HttpAuthHandlerMock());
3866 mock_handler->set_allows_default_credentials(true);
3867 auth_handler_factory->AddMockHandler(mock_handler.release(),
3868 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483869 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333870
3871 // Add NetLog just so can verify load timing information gets a NetLog ID.
3872 NetLog net_log;
3873 session_deps_.net_log = &net_log;
mmenkee65e7af2015-10-13 17:16:423874 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333875
3876 // Should try to establish tunnel.
3877 MockWrite data_writes1[] = {
3878 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173879 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333880 "Proxy-Connection: keep-alive\r\n\r\n"),
3881 };
3882
3883 // The proxy responds to the connect with a 407, using a non-persistent
3884 // connection.
3885 MockRead data_reads1[] = {
3886 // No credentials.
3887 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3888 MockRead("Proxy-Authenticate: Mock\r\n"),
3889 MockRead("Proxy-Connection: close\r\n\r\n"),
3890 };
3891
3892 // Since the first connection was closed, need to establish another once given
3893 // credentials.
3894 MockWrite data_writes2[] = {
3895 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173896 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333897 "Proxy-Connection: keep-alive\r\n"
3898 "Proxy-Authorization: auth_token\r\n\r\n"),
3899 };
3900
3901 MockRead data_reads2[] = {
3902 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3903 MockRead("Proxy-Authenticate: Mock\r\n"),
3904 MockRead("Proxy-Connection: close\r\n\r\n"),
3905 };
3906
3907 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3908 data_writes1, arraysize(data_writes1));
3909 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3910 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3911 data_writes2, arraysize(data_writes2));
3912 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3913 SSLSocketDataProvider ssl(ASYNC, OK);
3914 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3915
3916 scoped_ptr<HttpTransaction> trans(
3917 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3918
3919 TestCompletionCallback callback;
3920 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3921 EXPECT_EQ(OK, callback.GetResult(rv));
3922
3923 const HttpResponseInfo* response = trans->GetResponseInfo();
3924 ASSERT_TRUE(response);
3925 ASSERT_TRUE(response->headers);
3926 EXPECT_EQ(407, response->headers->response_code());
3927 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3928 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3929 EXPECT_FALSE(response->auth_challenge);
3930
3931 LoadTimingInfo load_timing_info;
3932 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3933
3934 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
3935 EXPECT_EQ(OK, callback.GetResult(rv));
3936 response = trans->GetResponseInfo();
3937 ASSERT_TRUE(response);
3938 ASSERT_TRUE(response->headers);
3939 EXPECT_EQ(407, response->headers->response_code());
3940 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3941 EXPECT_TRUE(response->auth_challenge);
3942
3943 trans.reset();
3944 session->CloseAllConnections();
3945}
3946
[email protected]029c83b62013-01-24 05:28:203947// Test the load timing for HTTPS requests with an HTTP proxy.
[email protected]23e482282013-06-14 16:08:023948TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:203949 HttpRequestInfo request1;
3950 request1.method = "GET";
bncce36dca22015-04-21 22:11:233951 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:203952
3953 HttpRequestInfo request2;
3954 request2.method = "GET";
bncce36dca22015-04-21 22:11:233955 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:203956
3957 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033958 session_deps_.proxy_service = ProxyService::CreateFixed("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:513959 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073960 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:423961 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:203962
3963 // Since we have proxy, should try to establish tunnel.
3964 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:173965 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3966 "Host: www.example.org:443\r\n"
3967 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203968
rsleevidb16bb02015-11-12 23:47:173969 MockWrite("GET /1 HTTP/1.1\r\n"
3970 "Host: www.example.org\r\n"
3971 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203972
rsleevidb16bb02015-11-12 23:47:173973 MockWrite("GET /2 HTTP/1.1\r\n"
3974 "Host: www.example.org\r\n"
3975 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:203976 };
3977
3978 // The proxy responds to the connect with a 407, using a persistent
3979 // connection.
3980 MockRead data_reads1[] = {
3981 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3982
3983 MockRead("HTTP/1.1 200 OK\r\n"),
3984 MockRead("Content-Length: 1\r\n\r\n"),
3985 MockRead(SYNCHRONOUS, "1"),
3986
3987 MockRead("HTTP/1.1 200 OK\r\n"),
3988 MockRead("Content-Length: 2\r\n\r\n"),
3989 MockRead(SYNCHRONOUS, "22"),
3990 };
3991
3992 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3993 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073994 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:203995 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073996 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:203997
3998 TestCompletionCallback callback1;
[email protected]262eec82013-03-19 21:01:363999 scoped_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:504000 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204001
4002 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
4003 EXPECT_EQ(ERR_IO_PENDING, rv);
4004
4005 rv = callback1.WaitForResult();
4006 EXPECT_EQ(OK, rv);
4007
4008 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
4009 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:504010 ASSERT_TRUE(response1->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204011 EXPECT_EQ(1, response1->headers->GetContentLength());
4012
4013 LoadTimingInfo load_timing_info1;
4014 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
4015 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
4016
4017 trans1.reset();
4018
4019 TestCompletionCallback callback2;
[email protected]262eec82013-03-19 21:01:364020 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504021 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204022
4023 rv = trans2->Start(&request2, callback2.callback(), log.bound());
4024 EXPECT_EQ(ERR_IO_PENDING, rv);
4025
4026 rv = callback2.WaitForResult();
4027 EXPECT_EQ(OK, rv);
4028
4029 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
4030 ASSERT_TRUE(response2 != NULL);
[email protected]90499482013-06-01 00:39:504031 ASSERT_TRUE(response2->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204032 EXPECT_EQ(2, response2->headers->GetContentLength());
4033
4034 LoadTimingInfo load_timing_info2;
4035 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4036 TestLoadTimingReused(load_timing_info2);
4037
4038 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
4039
4040 trans2.reset();
4041 session->CloseAllConnections();
4042}
4043
4044// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
[email protected]23e482282013-06-14 16:08:024045TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:204046 HttpRequestInfo request1;
4047 request1.method = "GET";
bncce36dca22015-04-21 22:11:234048 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:204049
4050 HttpRequestInfo request2;
4051 request2.method = "GET";
bncce36dca22015-04-21 22:11:234052 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:204053
4054 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034055 session_deps_.proxy_service =
4056 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:514057 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074058 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424059 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:204060
4061 // Since we have proxy, should try to establish tunnel.
4062 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174063 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4064 "Host: www.example.org:443\r\n"
4065 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204066
rsleevidb16bb02015-11-12 23:47:174067 MockWrite("GET /1 HTTP/1.1\r\n"
4068 "Host: www.example.org\r\n"
4069 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204070
rsleevidb16bb02015-11-12 23:47:174071 MockWrite("GET /2 HTTP/1.1\r\n"
4072 "Host: www.example.org\r\n"
4073 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204074 };
4075
4076 // The proxy responds to the connect with a 407, using a persistent
4077 // connection.
4078 MockRead data_reads1[] = {
4079 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4080
4081 MockRead("HTTP/1.1 200 OK\r\n"),
4082 MockRead("Content-Length: 1\r\n\r\n"),
4083 MockRead(SYNCHRONOUS, "1"),
4084
4085 MockRead("HTTP/1.1 200 OK\r\n"),
4086 MockRead("Content-Length: 2\r\n\r\n"),
4087 MockRead(SYNCHRONOUS, "22"),
4088 };
4089
4090 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4091 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074092 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:204093 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074094 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:204095
4096 TestCompletionCallback callback1;
[email protected]262eec82013-03-19 21:01:364097 scoped_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:504098 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204099
4100 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
4101 EXPECT_EQ(ERR_IO_PENDING, rv);
4102
4103 rv = callback1.WaitForResult();
4104 EXPECT_EQ(OK, rv);
4105
4106 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
4107 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:504108 ASSERT_TRUE(response1->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204109 EXPECT_EQ(1, response1->headers->GetContentLength());
4110
4111 LoadTimingInfo load_timing_info1;
4112 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
4113 TestLoadTimingNotReusedWithPac(load_timing_info1,
4114 CONNECT_TIMING_HAS_SSL_TIMES);
4115
4116 trans1.reset();
4117
4118 TestCompletionCallback callback2;
[email protected]262eec82013-03-19 21:01:364119 scoped_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504120 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204121
4122 rv = trans2->Start(&request2, callback2.callback(), log.bound());
4123 EXPECT_EQ(ERR_IO_PENDING, rv);
4124
4125 rv = callback2.WaitForResult();
4126 EXPECT_EQ(OK, rv);
4127
4128 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
4129 ASSERT_TRUE(response2 != NULL);
[email protected]90499482013-06-01 00:39:504130 ASSERT_TRUE(response2->headers.get() != NULL);
[email protected]029c83b62013-01-24 05:28:204131 EXPECT_EQ(2, response2->headers->GetContentLength());
4132
4133 LoadTimingInfo load_timing_info2;
4134 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4135 TestLoadTimingReusedWithPac(load_timing_info2);
4136
4137 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
4138
4139 trans2.reset();
4140 session->CloseAllConnections();
4141}
4142
[email protected]2df19bb2010-08-25 20:13:464143// Test a simple get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024144TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:274145 HttpRequestInfo request;
4146 request.method = "GET";
bncce36dca22015-04-21 22:11:234147 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274148
[email protected]2df19bb2010-08-25 20:13:464149 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034150 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514151 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074152 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424153 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:464154
[email protected]2df19bb2010-08-25 20:13:464155 // Since we have proxy, should use full url
4156 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234157 MockWrite(
4158 "GET http://www.example.org/ HTTP/1.1\r\n"
4159 "Host: www.example.org\r\n"
4160 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:464161 };
4162
4163 MockRead data_reads1[] = {
4164 MockRead("HTTP/1.1 200 OK\r\n"),
4165 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4166 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064167 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:464168 };
4169
4170 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4171 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074172 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064173 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074174 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:464175
[email protected]49639fa2011-12-20 23:22:414176 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:464177
[email protected]262eec82013-03-19 21:01:364178 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504179 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504180
[email protected]49639fa2011-12-20 23:22:414181 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:464182 EXPECT_EQ(ERR_IO_PENDING, rv);
4183
4184 rv = callback1.WaitForResult();
4185 EXPECT_EQ(OK, rv);
4186
[email protected]58e32bb2013-01-21 18:23:254187 LoadTimingInfo load_timing_info;
4188 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4189 TestLoadTimingNotReused(load_timing_info,
4190 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4191
[email protected]2df19bb2010-08-25 20:13:464192 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504193 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464194
4195 EXPECT_TRUE(response->headers->IsKeepAlive());
4196 EXPECT_EQ(200, response->headers->response_code());
4197 EXPECT_EQ(100, response->headers->GetContentLength());
4198 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4199
4200 // The password prompt info should not be set.
4201 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4202}
4203
[email protected]7642b5ae2010-09-01 20:55:174204// Test a SPDY get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024205TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:274206 HttpRequestInfo request;
4207 request.method = "GET";
bncce36dca22015-04-21 22:11:234208 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274209 request.load_flags = 0;
4210
[email protected]7642b5ae2010-09-01 20:55:174211 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034212 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514213 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074214 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424215 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:174216
bncce36dca22015-04-21 22:11:234217 // fetch http://www.example.org/ via SPDY
[email protected]cdf8f7e72013-05-23 10:56:464218 scoped_ptr<SpdyFrame> req(
bnc38dcd392016-02-09 23:19:494219 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, false));
rch8e6c6c42015-05-01 14:05:134220 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]7642b5ae2010-09-01 20:55:174221
[email protected]23e482282013-06-14 16:08:024222 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4223 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:174224 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134225 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:174226 };
4227
rch8e6c6c42015-05-01 14:05:134228 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4229 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074230 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:174231
[email protected]8ddf8322012-02-23 18:08:064232 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384233 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:074234 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:174235
[email protected]49639fa2011-12-20 23:22:414236 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:174237
[email protected]262eec82013-03-19 21:01:364238 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504239 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504240
[email protected]49639fa2011-12-20 23:22:414241 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7642b5ae2010-09-01 20:55:174242 EXPECT_EQ(ERR_IO_PENDING, rv);
4243
4244 rv = callback1.WaitForResult();
4245 EXPECT_EQ(OK, rv);
4246
[email protected]58e32bb2013-01-21 18:23:254247 LoadTimingInfo load_timing_info;
4248 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4249 TestLoadTimingNotReused(load_timing_info,
4250 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4251
[email protected]7642b5ae2010-09-01 20:55:174252 const HttpResponseInfo* response = trans->GetResponseInfo();
4253 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504254 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024255 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:174256
4257 std::string response_data;
4258 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
[email protected]448d4ca52012-03-04 04:12:234259 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:174260}
4261
[email protected]1c173852014-06-19 12:51:504262// Verifies that a session which races and wins against the owning transaction
4263// (completing prior to host resolution), doesn't fail the transaction.
4264// Regression test for crbug.com/334413.
4265TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
4266 HttpRequestInfo request;
4267 request.method = "GET";
bncce36dca22015-04-21 22:11:234268 request.url = GURL("http://www.example.org/");
[email protected]1c173852014-06-19 12:51:504269 request.load_flags = 0;
4270
4271 // Configure SPDY proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034272 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514273 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:504274 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424275 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:504276
bncce36dca22015-04-21 22:11:234277 // Fetch http://www.example.org/ through the SPDY proxy.
[email protected]1c173852014-06-19 12:51:504278 scoped_ptr<SpdyFrame> req(
bnc38dcd392016-02-09 23:19:494279 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, false));
rch8e6c6c42015-05-01 14:05:134280 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]1c173852014-06-19 12:51:504281
4282 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4283 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
4284 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:134285 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:504286 };
4287
rch8e6c6c42015-05-01 14:05:134288 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4289 arraysize(spdy_writes));
[email protected]1c173852014-06-19 12:51:504290 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4291
4292 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:384293 ssl.SetNextProto(GetProtocol());
[email protected]1c173852014-06-19 12:51:504294 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4295
4296 TestCompletionCallback callback1;
4297
4298 scoped_ptr<HttpTransaction> trans(
4299 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4300
4301 // Stall the hostname resolution begun by the transaction.
4302 session_deps_.host_resolver->set_synchronous_mode(false);
4303 session_deps_.host_resolver->set_ondemand_mode(true);
4304
4305 int rv = trans->Start(&request, callback1.callback(), log.bound());
4306 EXPECT_EQ(ERR_IO_PENDING, rv);
4307
4308 // Race a session to the proxy, which completes first.
4309 session_deps_.host_resolver->set_ondemand_mode(false);
4310 SpdySessionKey key(
4311 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
4312 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:424313 CreateSecureSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:504314
4315 // Unstall the resolution begun by the transaction.
4316 session_deps_.host_resolver->set_ondemand_mode(true);
4317 session_deps_.host_resolver->ResolveAllPending();
4318
4319 EXPECT_FALSE(callback1.have_result());
4320 rv = callback1.WaitForResult();
4321 EXPECT_EQ(OK, rv);
4322
4323 const HttpResponseInfo* response = trans->GetResponseInfo();
4324 ASSERT_TRUE(response != NULL);
4325 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:024326 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:504327
4328 std::string response_data;
4329 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4330 EXPECT_EQ(kUploadData, response_data);
4331}
4332
[email protected]dc7bd1c52010-11-12 00:01:134333// Test a SPDY get through an HTTPS Proxy.
[email protected]23e482282013-06-14 16:08:024334TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:274335 HttpRequestInfo request;
4336 request.method = "GET";
bncce36dca22015-04-21 22:11:234337 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274338 request.load_flags = 0;
4339
[email protected]79cb5c12011-09-12 13:12:044340 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034341 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:514342 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074343 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:424344 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:134345
[email protected]dc7bd1c52010-11-12 00:01:134346 // The first request will be a bare GET, the second request will be a
4347 // GET with a Proxy-Authorization header.
[email protected]ff98d7f02012-03-22 21:44:194348 scoped_ptr<SpdyFrame> req_get(
bnc38dcd392016-02-09 23:19:494349 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, false));
rdsmithebb50aa2015-11-12 03:44:384350 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:134351 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464352 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:134353 };
[email protected]ff98d7f02012-03-22 21:44:194354 scoped_ptr<SpdyFrame> req_get_authorization(
[email protected]cdf8f7e72013-05-23 10:56:464355 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4356 arraysize(kExtraAuthorizationHeaders) / 2,
[email protected]cdf8f7e72013-05-23 10:56:464357 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(
bnc38dcd392016-02-09 23:19:494541 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 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(
bnc38dcd392016-02-09 23:19:494718 spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, 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(
bnc38dcd392016-02-09 23:19:494954 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, 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(
bnc38dcd392016-02-09 23:19:494965 spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, 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.
tbansal28e68f82016-02-04 02:56:157692TEST_P(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
7693 // Configure the proxy delegate to allow cross-origin SPDY pushes.
7694 scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
7695 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
7696 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:297697 HttpRequestInfo request;
7698 HttpRequestInfo push_request;
7699
[email protected]7c6f7ba2012-04-03 04:09:297700 request.method = "GET";
bncce36dca22015-04-21 22:11:237701 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:297702 push_request.method = "GET";
7703 push_request.url = GURL("http://www.another-origin.com/foo.dat");
7704
tbansal28e68f82016-02-04 02:56:157705 // Configure against https proxy server "myproxy:443".
rdsmith82957ad2015-09-16 19:42:037706 session_deps_.proxy_service =
tbansal28e68f82016-02-04 02:56:157707 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:443");
vishal.b62985ca92015-04-17 08:45:517708 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077709 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:507710
tbansal28e68f82016-02-04 02:56:157711 session_deps_.proxy_delegate.reset(proxy_delegate.release());
[email protected]61b4efc2012-04-27 18:12:507712
mmenkee65e7af2015-10-13 17:16:427713 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:297714
[email protected]cdf8f7e72013-05-23 10:56:467715 scoped_ptr<SpdyFrame> stream1_syn(
bnc38dcd392016-02-09 23:19:497716 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, false));
[email protected]7c6f7ba2012-04-03 04:09:297717
7718 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137719 CreateMockWrite(*stream1_syn, 0, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:297720 };
7721
7722 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027723 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:297724
7725 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027726 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:297727
7728 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027729 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]7c6f7ba2012-04-03 04:09:297730 0,
7731 2,
7732 1,
7733 "http://www.another-origin.com/foo.dat"));
[email protected]8a0fc822013-06-27 20:52:437734 const char kPushedData[] = "pushed";
7735 scoped_ptr<SpdyFrame> stream2_body(
7736 spdy_util_.ConstructSpdyBodyFrame(
7737 2, kPushedData, strlen(kPushedData), true));
[email protected]7c6f7ba2012-04-03 04:09:297738
7739 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137740 CreateMockRead(*stream1_reply, 1, ASYNC),
7741 CreateMockRead(*stream2_syn, 2, ASYNC),
7742 CreateMockRead(*stream1_body, 3, ASYNC),
7743 CreateMockRead(*stream2_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:597744 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:297745 };
7746
rch8e6c6c42015-05-01 14:05:137747 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7748 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077749 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:297750 // Negotiate SPDY to the proxy
7751 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387752 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077753 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:297754
[email protected]262eec82013-03-19 21:01:367755 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507756 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7c6f7ba2012-04-03 04:09:297757 TestCompletionCallback callback;
7758 int rv = trans->Start(&request, callback.callback(), log.bound());
7759 EXPECT_EQ(ERR_IO_PENDING, rv);
7760
7761 rv = callback.WaitForResult();
7762 EXPECT_EQ(OK, rv);
7763 const HttpResponseInfo* response = trans->GetResponseInfo();
7764
[email protected]262eec82013-03-19 21:01:367765 scoped_ptr<HttpTransaction> push_trans(
[email protected]90499482013-06-01 00:39:507766 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7767 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
[email protected]7c6f7ba2012-04-03 04:09:297768 EXPECT_EQ(ERR_IO_PENDING, rv);
7769
7770 rv = callback.WaitForResult();
7771 EXPECT_EQ(OK, rv);
7772 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
7773
7774 ASSERT_TRUE(response != NULL);
7775 EXPECT_TRUE(response->headers->IsKeepAlive());
7776
7777 EXPECT_EQ(200, response->headers->response_code());
7778 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7779
7780 std::string response_data;
7781 rv = ReadTransaction(trans.get(), &response_data);
7782 EXPECT_EQ(OK, rv);
7783 EXPECT_EQ("hello!", response_data);
7784
[email protected]029c83b62013-01-24 05:28:207785 LoadTimingInfo load_timing_info;
7786 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7787 TestLoadTimingNotReusedWithPac(load_timing_info,
7788 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7789
[email protected]7c6f7ba2012-04-03 04:09:297790 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:507791 EXPECT_TRUE(push_response->headers.get() != NULL);
[email protected]7c6f7ba2012-04-03 04:09:297792 EXPECT_EQ(200, push_response->headers->response_code());
7793
7794 rv = ReadTransaction(push_trans.get(), &response_data);
7795 EXPECT_EQ(OK, rv);
7796 EXPECT_EQ("pushed", response_data);
7797
[email protected]029c83b62013-01-24 05:28:207798 LoadTimingInfo push_load_timing_info;
7799 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
7800 TestLoadTimingReusedWithPac(push_load_timing_info);
7801 // The transactions should share a socket ID, despite being for different
7802 // origins.
7803 EXPECT_EQ(load_timing_info.socket_log_id,
7804 push_load_timing_info.socket_log_id);
7805
[email protected]7c6f7ba2012-04-03 04:09:297806 trans.reset();
7807 push_trans.reset();
7808 session->CloseAllConnections();
7809}
7810
[email protected]8c843192012-04-05 07:15:007811// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
[email protected]23e482282013-06-14 16:08:027812TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:157813 // Configure the proxy delegate to allow cross-origin SPDY pushes.
7814 scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
7815 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
7816 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:007817 HttpRequestInfo request;
7818
7819 request.method = "GET";
bncce36dca22015-04-21 22:11:237820 request.url = GURL("http://www.example.org/");
[email protected]8c843192012-04-05 07:15:007821
tbansal28e68f82016-02-04 02:56:157822 session_deps_.proxy_service =
7823 ProxyService::CreateFixed("https://myproxy:443");
vishal.b62985ca92015-04-17 08:45:517824 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077825 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:507826
7827 // Enable cross-origin push.
tbansal28e68f82016-02-04 02:56:157828 session_deps_.proxy_delegate.reset(proxy_delegate.release());
[email protected]61b4efc2012-04-27 18:12:507829
mmenkee65e7af2015-10-13 17:16:427830 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:007831
[email protected]cdf8f7e72013-05-23 10:56:467832 scoped_ptr<SpdyFrame> stream1_syn(
bnc38dcd392016-02-09 23:19:497833 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, false));
[email protected]8c843192012-04-05 07:15:007834
7835 scoped_ptr<SpdyFrame> push_rst(
[email protected]c10b20852013-05-15 21:29:207836 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:007837
7838 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:137839 CreateMockWrite(*stream1_syn, 0, ASYNC), CreateMockWrite(*push_rst, 3),
[email protected]8c843192012-04-05 07:15:007840 };
7841
7842 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027843 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8c843192012-04-05 07:15:007844
7845 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027846 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]8c843192012-04-05 07:15:007847
7848 scoped_ptr<SpdyFrame>
[email protected]23e482282013-06-14 16:08:027849 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]8c843192012-04-05 07:15:007850 0,
7851 2,
7852 1,
7853 "https://www.another-origin.com/foo.dat"));
7854
7855 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:137856 CreateMockRead(*stream1_reply, 1, ASYNC),
7857 CreateMockRead(*stream2_syn, 2, ASYNC),
7858 CreateMockRead(*stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:597859 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:007860 };
7861
rch8e6c6c42015-05-01 14:05:137862 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7863 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077864 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:007865 // Negotiate SPDY to the proxy
7866 SSLSocketDataProvider proxy(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:387867 proxy.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:077868 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:007869
[email protected]262eec82013-03-19 21:01:367870 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507871 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c843192012-04-05 07:15:007872 TestCompletionCallback callback;
7873 int rv = trans->Start(&request, callback.callback(), log.bound());
7874 EXPECT_EQ(ERR_IO_PENDING, rv);
7875
7876 rv = callback.WaitForResult();
7877 EXPECT_EQ(OK, rv);
7878 const HttpResponseInfo* response = trans->GetResponseInfo();
7879
7880 ASSERT_TRUE(response != NULL);
7881 EXPECT_TRUE(response->headers->IsKeepAlive());
7882
7883 EXPECT_EQ(200, response->headers->response_code());
7884 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7885
7886 std::string response_data;
7887 rv = ReadTransaction(trans.get(), &response_data);
7888 EXPECT_EQ(OK, rv);
7889 EXPECT_EQ("hello!", response_data);
7890
7891 trans.reset();
7892 session->CloseAllConnections();
7893}
7894
tbansal8ef1d3e2016-02-03 04:05:427895// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
7896// resources.
7897TEST_P(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:157898 // Configure the proxy delegate to allow cross-origin SPDY pushes.
7899 scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
7900 proxy_delegate->set_trusted_spdy_proxy(
7901 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
7902
tbansal8ef1d3e2016-02-03 04:05:427903 HttpRequestInfo request;
7904
7905 request.method = "GET";
7906 request.url = GURL("http://www.example.org/");
7907
7908 // Configure against https proxy server "myproxy:70".
7909 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
7910 BoundTestNetLog log;
7911 session_deps_.net_log = log.bound().net_log();
7912
7913 // Enable cross-origin push.
tbansal28e68f82016-02-04 02:56:157914 session_deps_.proxy_delegate.reset(proxy_delegate.release());
tbansal8ef1d3e2016-02-03 04:05:427915
7916 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7917
7918 scoped_ptr<SpdyFrame> stream1_syn(
bnc38dcd392016-02-09 23:19:497919 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, false));
tbansal8ef1d3e2016-02-03 04:05:427920
7921 MockWrite spdy_writes[] = {
7922 CreateMockWrite(*stream1_syn, 0, ASYNC),
7923 };
7924
7925 scoped_ptr<SpdyFrame> stream1_reply(
7926 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
7927
bnc38dcd392016-02-09 23:19:497928 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
7929 nullptr, 0, 2, 1, "https://myproxy:70/foo.dat"));
7930
tbansal8ef1d3e2016-02-03 04:05:427931 scoped_ptr<SpdyFrame> stream1_body(
7932 spdy_util_.ConstructSpdyBodyFrame(1, true));
7933
7934 scoped_ptr<SpdyFrame> stream2_reply(
7935 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
7936
7937 scoped_ptr<SpdyFrame> stream2_body(
7938 spdy_util_.ConstructSpdyBodyFrame(1, true));
7939
7940 MockRead spdy_reads[] = {
7941 CreateMockRead(*stream1_reply, 1, ASYNC),
7942 CreateMockRead(*stream2_syn, 2, ASYNC),
7943 CreateMockRead(*stream1_body, 3, ASYNC),
7944 CreateMockRead(*stream2_body, 4, ASYNC),
7945 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
7946 };
7947
7948 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7949 arraysize(spdy_writes));
7950 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7951 // Negotiate SPDY to the proxy
7952 SSLSocketDataProvider proxy(ASYNC, OK);
7953 proxy.SetNextProto(GetProtocol());
7954 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
7955
7956 scoped_ptr<HttpTransaction> trans(
7957 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7958 TestCompletionCallback callback;
7959 int rv = trans->Start(&request, callback.callback(), log.bound());
7960 EXPECT_EQ(ERR_IO_PENDING, rv);
7961
7962 rv = callback.WaitForResult();
7963 EXPECT_EQ(OK, rv);
7964 const HttpResponseInfo* response = trans->GetResponseInfo();
7965
7966 ASSERT_TRUE(response != nullptr);
7967 EXPECT_TRUE(response->headers->IsKeepAlive());
7968
7969 EXPECT_EQ(200, response->headers->response_code());
7970 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7971
7972 std::string response_data;
7973 rv = ReadTransaction(trans.get(), &response_data);
7974 EXPECT_EQ(OK, rv);
7975 EXPECT_EQ("hello!", response_data);
7976
7977 trans.reset();
7978 session->CloseAllConnections();
7979}
7980
[email protected]2df19bb2010-08-25 20:13:467981// Test HTTPS connections to a site with a bad certificate, going through an
7982// HTTPS proxy
[email protected]23e482282013-06-14 16:08:027983TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037984 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]2df19bb2010-08-25 20:13:467985
7986 HttpRequestInfo request;
7987 request.method = "GET";
bncce36dca22015-04-21 22:11:237988 request.url = GURL("https://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467989 request.load_flags = 0;
7990
7991 // Attempt to fetch the URL from a server with a bad cert
7992 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:177993 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7994 "Host: www.example.org:443\r\n"
7995 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467996 };
7997
7998 MockRead bad_cert_reads[] = {
7999 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068000 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:468001 };
8002
8003 // Attempt to fetch the URL with a good cert
8004 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:178005 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8006 "Host: www.example.org:443\r\n"
8007 "Proxy-Connection: keep-alive\r\n\r\n"),
8008 MockWrite("GET / HTTP/1.1\r\n"
8009 "Host: www.example.org\r\n"
8010 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:468011 };
8012
8013 MockRead good_cert_reads[] = {
8014 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
8015 MockRead("HTTP/1.0 200 OK\r\n"),
8016 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8017 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068018 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:468019 };
8020
8021 StaticSocketDataProvider ssl_bad_certificate(
8022 bad_cert_reads, arraysize(bad_cert_reads),
8023 bad_cert_writes, arraysize(bad_cert_writes));
8024 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
8025 good_data_writes, arraysize(good_data_writes));
[email protected]8ddf8322012-02-23 18:08:068026 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
8027 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:468028
8029 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:078030 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8031 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
8032 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:468033
8034 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:078035 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8036 session_deps_.socket_factory->AddSocketDataProvider(&data);
8037 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:468038
[email protected]49639fa2011-12-20 23:22:418039 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:468040
mmenkee65e7af2015-10-13 17:16:428041 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:468042 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418043 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2df19bb2010-08-25 20:13:468044
[email protected]49639fa2011-12-20 23:22:418045 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:468046 EXPECT_EQ(ERR_IO_PENDING, rv);
8047
8048 rv = callback.WaitForResult();
8049 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
8050
[email protected]49639fa2011-12-20 23:22:418051 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]2df19bb2010-08-25 20:13:468052 EXPECT_EQ(ERR_IO_PENDING, rv);
8053
8054 rv = callback.WaitForResult();
8055 EXPECT_EQ(OK, rv);
8056
8057 const HttpResponseInfo* response = trans->GetResponseInfo();
8058
[email protected]fe2255a2011-09-20 19:37:508059 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:468060 EXPECT_EQ(100, response->headers->GetContentLength());
8061}
8062
[email protected]23e482282013-06-14 16:08:028063TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:428064 HttpRequestInfo request;
8065 request.method = "GET";
bncce36dca22015-04-21 22:11:238066 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438067 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
8068 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:428069
mmenkee65e7af2015-10-13 17:16:428070 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278071 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418072 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278073
[email protected]1c773ea12009-04-28 19:58:428074 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238075 MockWrite(
8076 "GET / HTTP/1.1\r\n"
8077 "Host: www.example.org\r\n"
8078 "Connection: keep-alive\r\n"
8079 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428080 };
8081
8082 // Lastly, the server responds with the actual content.
8083 MockRead data_reads[] = {
8084 MockRead("HTTP/1.0 200 OK\r\n"),
8085 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8086 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068087 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428088 };
8089
[email protected]31a2bfe2010-02-09 08:03:398090 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8091 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078092 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428093
[email protected]49639fa2011-12-20 23:22:418094 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428095
[email protected]49639fa2011-12-20 23:22:418096 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428097 EXPECT_EQ(ERR_IO_PENDING, rv);
8098
8099 rv = callback.WaitForResult();
8100 EXPECT_EQ(OK, rv);
8101}
8102
[email protected]23e482282013-06-14 16:08:028103TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:298104 HttpRequestInfo request;
8105 request.method = "GET";
bncce36dca22015-04-21 22:11:238106 request.url = GURL("https://www.example.org/");
[email protected]da81f132010-08-18 23:39:298107 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
8108 "Chromium Ultra Awesome X Edition");
8109
rdsmith82957ad2015-09-16 19:42:038110 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
mmenkee65e7af2015-10-13 17:16:428111 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278112 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418113 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278114
[email protected]da81f132010-08-18 23:39:298115 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:178116 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8117 "Host: www.example.org:443\r\n"
8118 "Proxy-Connection: keep-alive\r\n"
8119 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]da81f132010-08-18 23:39:298120 };
8121 MockRead data_reads[] = {
8122 // Return an error, so the transaction stops here (this test isn't
8123 // interested in the rest).
8124 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
8125 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8126 MockRead("Proxy-Connection: close\r\n\r\n"),
8127 };
8128
8129 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8130 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078131 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:298132
[email protected]49639fa2011-12-20 23:22:418133 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:298134
[email protected]49639fa2011-12-20 23:22:418135 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]da81f132010-08-18 23:39:298136 EXPECT_EQ(ERR_IO_PENDING, rv);
8137
8138 rv = callback.WaitForResult();
8139 EXPECT_EQ(OK, rv);
8140}
8141
[email protected]23e482282013-06-14 16:08:028142TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:428143 HttpRequestInfo request;
8144 request.method = "GET";
bncce36dca22015-04-21 22:11:238145 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428146 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:168147 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
8148 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:428149
mmenkee65e7af2015-10-13 17:16:428150 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278151 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418152 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278153
[email protected]1c773ea12009-04-28 19:58:428154 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238155 MockWrite(
8156 "GET / HTTP/1.1\r\n"
8157 "Host: www.example.org\r\n"
8158 "Connection: keep-alive\r\n"
8159 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428160 };
8161
8162 // Lastly, the server responds with the actual content.
8163 MockRead data_reads[] = {
8164 MockRead("HTTP/1.0 200 OK\r\n"),
8165 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8166 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068167 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428168 };
8169
[email protected]31a2bfe2010-02-09 08:03:398170 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8171 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078172 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428173
[email protected]49639fa2011-12-20 23:22:418174 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428175
[email protected]49639fa2011-12-20 23:22:418176 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428177 EXPECT_EQ(ERR_IO_PENDING, rv);
8178
8179 rv = callback.WaitForResult();
8180 EXPECT_EQ(OK, rv);
8181}
8182
[email protected]23e482282013-06-14 16:08:028183TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428184 HttpRequestInfo request;
8185 request.method = "POST";
bncce36dca22015-04-21 22:11:238186 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428187
mmenkee65e7af2015-10-13 17:16:428188 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278189 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418190 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278191
[email protected]1c773ea12009-04-28 19:58:428192 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238193 MockWrite(
8194 "POST / HTTP/1.1\r\n"
8195 "Host: www.example.org\r\n"
8196 "Connection: keep-alive\r\n"
8197 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428198 };
8199
8200 // Lastly, the server responds with the actual content.
8201 MockRead data_reads[] = {
8202 MockRead("HTTP/1.0 200 OK\r\n"),
8203 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8204 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068205 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428206 };
8207
[email protected]31a2bfe2010-02-09 08:03:398208 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8209 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078210 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428211
[email protected]49639fa2011-12-20 23:22:418212 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428213
[email protected]49639fa2011-12-20 23:22:418214 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428215 EXPECT_EQ(ERR_IO_PENDING, rv);
8216
8217 rv = callback.WaitForResult();
8218 EXPECT_EQ(OK, rv);
8219}
8220
[email protected]23e482282013-06-14 16:08:028221TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428222 HttpRequestInfo request;
8223 request.method = "PUT";
bncce36dca22015-04-21 22:11:238224 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428225
mmenkee65e7af2015-10-13 17:16:428226 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278227 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418228 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278229
[email protected]1c773ea12009-04-28 19:58:428230 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238231 MockWrite(
8232 "PUT / HTTP/1.1\r\n"
8233 "Host: www.example.org\r\n"
8234 "Connection: keep-alive\r\n"
8235 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428236 };
8237
8238 // Lastly, the server responds with the actual content.
8239 MockRead data_reads[] = {
8240 MockRead("HTTP/1.0 200 OK\r\n"),
8241 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8242 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068243 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428244 };
8245
[email protected]31a2bfe2010-02-09 08:03:398246 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8247 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078248 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428249
[email protected]49639fa2011-12-20 23:22:418250 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428251
[email protected]49639fa2011-12-20 23:22:418252 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428253 EXPECT_EQ(ERR_IO_PENDING, rv);
8254
8255 rv = callback.WaitForResult();
8256 EXPECT_EQ(OK, rv);
8257}
8258
[email protected]23e482282013-06-14 16:08:028259TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428260 HttpRequestInfo request;
8261 request.method = "HEAD";
bncce36dca22015-04-21 22:11:238262 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428263
mmenkee65e7af2015-10-13 17:16:428264 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278265 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418266 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278267
[email protected]1c773ea12009-04-28 19:58:428268 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:138269 MockWrite("HEAD / HTTP/1.1\r\n"
8270 "Host: www.example.org\r\n"
8271 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428272 };
8273
8274 // Lastly, the server responds with the actual content.
8275 MockRead data_reads[] = {
8276 MockRead("HTTP/1.0 200 OK\r\n"),
8277 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8278 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068279 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428280 };
8281
[email protected]31a2bfe2010-02-09 08:03:398282 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8283 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078284 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428285
[email protected]49639fa2011-12-20 23:22:418286 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428287
[email protected]49639fa2011-12-20 23:22:418288 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428289 EXPECT_EQ(ERR_IO_PENDING, rv);
8290
8291 rv = callback.WaitForResult();
8292 EXPECT_EQ(OK, rv);
8293}
8294
[email protected]23e482282013-06-14 16:08:028295TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:428296 HttpRequestInfo request;
8297 request.method = "GET";
bncce36dca22015-04-21 22:11:238298 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428299 request.load_flags = LOAD_BYPASS_CACHE;
8300
mmenkee65e7af2015-10-13 17:16:428301 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278302 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418303 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278304
[email protected]1c773ea12009-04-28 19:58:428305 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238306 MockWrite(
8307 "GET / HTTP/1.1\r\n"
8308 "Host: www.example.org\r\n"
8309 "Connection: keep-alive\r\n"
8310 "Pragma: no-cache\r\n"
8311 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428312 };
8313
8314 // Lastly, the server responds with the actual content.
8315 MockRead data_reads[] = {
8316 MockRead("HTTP/1.0 200 OK\r\n"),
8317 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8318 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068319 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428320 };
8321
[email protected]31a2bfe2010-02-09 08:03:398322 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8323 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078324 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428325
[email protected]49639fa2011-12-20 23:22:418326 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428327
[email protected]49639fa2011-12-20 23:22:418328 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428329 EXPECT_EQ(ERR_IO_PENDING, rv);
8330
8331 rv = callback.WaitForResult();
8332 EXPECT_EQ(OK, rv);
8333}
8334
[email protected]23e482282013-06-14 16:08:028335TEST_P(HttpNetworkTransactionTest,
[email protected]1c773ea12009-04-28 19:58:428336 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:428337 HttpRequestInfo request;
8338 request.method = "GET";
bncce36dca22015-04-21 22:11:238339 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428340 request.load_flags = LOAD_VALIDATE_CACHE;
8341
mmenkee65e7af2015-10-13 17:16:428342 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278343 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418344 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278345
[email protected]1c773ea12009-04-28 19:58:428346 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238347 MockWrite(
8348 "GET / HTTP/1.1\r\n"
8349 "Host: www.example.org\r\n"
8350 "Connection: keep-alive\r\n"
8351 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428352 };
8353
8354 // Lastly, the server responds with the actual content.
8355 MockRead data_reads[] = {
8356 MockRead("HTTP/1.0 200 OK\r\n"),
8357 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8358 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068359 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428360 };
8361
[email protected]31a2bfe2010-02-09 08:03:398362 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8363 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078364 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428365
[email protected]49639fa2011-12-20 23:22:418366 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428367
[email protected]49639fa2011-12-20 23:22:418368 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428369 EXPECT_EQ(ERR_IO_PENDING, rv);
8370
8371 rv = callback.WaitForResult();
8372 EXPECT_EQ(OK, rv);
8373}
8374
[email protected]23e482282013-06-14 16:08:028375TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:428376 HttpRequestInfo request;
8377 request.method = "GET";
bncce36dca22015-04-21 22:11:238378 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438379 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:428380
mmenkee65e7af2015-10-13 17:16:428381 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278382 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418383 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278384
[email protected]1c773ea12009-04-28 19:58:428385 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238386 MockWrite(
8387 "GET / HTTP/1.1\r\n"
8388 "Host: www.example.org\r\n"
8389 "Connection: keep-alive\r\n"
8390 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428391 };
8392
8393 // Lastly, the server responds with the actual content.
8394 MockRead data_reads[] = {
8395 MockRead("HTTP/1.0 200 OK\r\n"),
8396 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8397 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068398 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428399 };
8400
[email protected]31a2bfe2010-02-09 08:03:398401 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8402 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078403 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428404
[email protected]49639fa2011-12-20 23:22:418405 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428406
[email protected]49639fa2011-12-20 23:22:418407 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:428408 EXPECT_EQ(ERR_IO_PENDING, rv);
8409
8410 rv = callback.WaitForResult();
8411 EXPECT_EQ(OK, rv);
8412}
8413
[email protected]23e482282013-06-14 16:08:028414TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:478415 HttpRequestInfo request;
8416 request.method = "GET";
bncce36dca22015-04-21 22:11:238417 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438418 request.extra_headers.SetHeader("referer", "www.foo.com");
8419 request.extra_headers.SetHeader("hEllo", "Kitty");
8420 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:478421
mmenkee65e7af2015-10-13 17:16:428422 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278423 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418424 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278425
[email protected]270c6412010-03-29 22:02:478426 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238427 MockWrite(
8428 "GET / HTTP/1.1\r\n"
8429 "Host: www.example.org\r\n"
8430 "Connection: keep-alive\r\n"
8431 "referer: www.foo.com\r\n"
8432 "hEllo: Kitty\r\n"
8433 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:478434 };
8435
8436 // Lastly, the server responds with the actual content.
8437 MockRead data_reads[] = {
8438 MockRead("HTTP/1.0 200 OK\r\n"),
8439 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8440 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068441 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:478442 };
8443
8444 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8445 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078446 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:478447
[email protected]49639fa2011-12-20 23:22:418448 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:478449
[email protected]49639fa2011-12-20 23:22:418450 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]270c6412010-03-29 22:02:478451 EXPECT_EQ(ERR_IO_PENDING, rv);
8452
8453 rv = callback.WaitForResult();
8454 EXPECT_EQ(OK, rv);
8455}
8456
[email protected]23e482282013-06-14 16:08:028457TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278458 HttpRequestInfo request;
8459 request.method = "GET";
bncce36dca22015-04-21 22:11:238460 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278461 request.load_flags = 0;
8462
rdsmith82957ad2015-09-16 19:42:038463 session_deps_.proxy_service =
8464 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518465 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078466 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028467
mmenkee65e7af2015-10-13 17:16:428468 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3cd17242009-06-23 02:59:028469 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418470 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028471
[email protected]3cd17242009-06-23 02:59:028472 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8473 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8474
8475 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238476 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8477 MockWrite(
8478 "GET / HTTP/1.1\r\n"
8479 "Host: www.example.org\r\n"
8480 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028481
8482 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:068483 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:028484 MockRead("HTTP/1.0 200 OK\r\n"),
8485 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8486 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068487 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028488 };
8489
[email protected]31a2bfe2010-02-09 08:03:398490 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8491 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078492 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028493
[email protected]49639fa2011-12-20 23:22:418494 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028495
[email protected]49639fa2011-12-20 23:22:418496 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:028497 EXPECT_EQ(ERR_IO_PENDING, rv);
8498
8499 rv = callback.WaitForResult();
8500 EXPECT_EQ(OK, rv);
8501
8502 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508503 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:028504
[email protected]029c83b62013-01-24 05:28:208505 LoadTimingInfo load_timing_info;
8506 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8507 TestLoadTimingNotReusedWithPac(load_timing_info,
8508 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8509
[email protected]3cd17242009-06-23 02:59:028510 std::string response_text;
8511 rv = ReadTransaction(trans.get(), &response_text);
8512 EXPECT_EQ(OK, rv);
8513 EXPECT_EQ("Payload", response_text);
8514}
8515
[email protected]23e482282013-06-14 16:08:028516TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278517 HttpRequestInfo request;
8518 request.method = "GET";
bncce36dca22015-04-21 22:11:238519 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278520 request.load_flags = 0;
8521
rdsmith82957ad2015-09-16 19:42:038522 session_deps_.proxy_service =
8523 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518524 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078525 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028526
mmenkee65e7af2015-10-13 17:16:428527 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3cd17242009-06-23 02:59:028528 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418529 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028530
[email protected]3cd17242009-06-23 02:59:028531 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
8532 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8533
8534 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238535 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
8536 arraysize(write_buffer)),
8537 MockWrite(
8538 "GET / HTTP/1.1\r\n"
8539 "Host: www.example.org\r\n"
8540 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028541
8542 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018543 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
8544 arraysize(read_buffer)),
[email protected]e0c27be2009-07-15 13:09:358545 MockRead("HTTP/1.0 200 OK\r\n"),
8546 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8547 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068548 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358549 };
8550
[email protected]31a2bfe2010-02-09 08:03:398551 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8552 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078553 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358554
[email protected]8ddf8322012-02-23 18:08:068555 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078556 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:358557
[email protected]49639fa2011-12-20 23:22:418558 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358559
[email protected]49639fa2011-12-20 23:22:418560 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:358561 EXPECT_EQ(ERR_IO_PENDING, rv);
8562
8563 rv = callback.WaitForResult();
8564 EXPECT_EQ(OK, rv);
8565
[email protected]029c83b62013-01-24 05:28:208566 LoadTimingInfo load_timing_info;
8567 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8568 TestLoadTimingNotReusedWithPac(load_timing_info,
8569 CONNECT_TIMING_HAS_SSL_TIMES);
8570
[email protected]e0c27be2009-07-15 13:09:358571 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508572 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:358573
8574 std::string response_text;
8575 rv = ReadTransaction(trans.get(), &response_text);
8576 EXPECT_EQ(OK, rv);
8577 EXPECT_EQ("Payload", response_text);
8578}
8579
[email protected]23e482282013-06-14 16:08:028580TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:208581 HttpRequestInfo request;
8582 request.method = "GET";
bncce36dca22015-04-21 22:11:238583 request.url = GURL("http://www.example.org/");
[email protected]029c83b62013-01-24 05:28:208584 request.load_flags = 0;
8585
rdsmith82957ad2015-09-16 19:42:038586 session_deps_.proxy_service =
8587 ProxyService::CreateFixed("socks4://myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518588 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078589 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:208590
mmenkee65e7af2015-10-13 17:16:428591 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:208592 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418593 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:208594
8595 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8596 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8597
8598 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238599 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8600 MockWrite(
8601 "GET / HTTP/1.1\r\n"
8602 "Host: www.example.org\r\n"
8603 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:208604
8605 MockRead data_reads[] = {
8606 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
8607 MockRead("HTTP/1.0 200 OK\r\n"),
8608 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8609 MockRead("Payload"),
8610 MockRead(SYNCHRONOUS, OK)
8611 };
8612
8613 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8614 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078615 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:208616
8617 TestCompletionCallback callback;
8618
8619 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8620 EXPECT_EQ(ERR_IO_PENDING, rv);
8621
8622 rv = callback.WaitForResult();
8623 EXPECT_EQ(OK, rv);
8624
8625 const HttpResponseInfo* response = trans->GetResponseInfo();
8626 ASSERT_TRUE(response != NULL);
8627
8628 LoadTimingInfo load_timing_info;
8629 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8630 TestLoadTimingNotReused(load_timing_info,
8631 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8632
8633 std::string response_text;
8634 rv = ReadTransaction(trans.get(), &response_text);
8635 EXPECT_EQ(OK, rv);
8636 EXPECT_EQ("Payload", response_text);
8637}
8638
[email protected]23e482282013-06-14 16:08:028639TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278640 HttpRequestInfo request;
8641 request.method = "GET";
bncce36dca22015-04-21 22:11:238642 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278643 request.load_flags = 0;
8644
rdsmith82957ad2015-09-16 19:42:038645 session_deps_.proxy_service =
8646 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518647 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078648 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358649
mmenkee65e7af2015-10-13 17:16:428650 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e0c27be2009-07-15 13:09:358651 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418652 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358653
[email protected]e0c27be2009-07-15 13:09:358654 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8655 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378656 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238657 0x05, // Version
8658 0x01, // Command (CONNECT)
8659 0x00, // Reserved.
8660 0x03, // Address type (DOMAINNAME).
8661 0x0F, // Length of domain (15)
8662 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8663 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:378664 };
[email protected]e0c27be2009-07-15 13:09:358665 const char kSOCKS5OkResponse[] =
8666 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
8667
8668 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238669 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8670 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
8671 MockWrite(
8672 "GET / HTTP/1.1\r\n"
8673 "Host: www.example.org\r\n"
8674 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358675
8676 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018677 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8678 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]e0c27be2009-07-15 13:09:358679 MockRead("HTTP/1.0 200 OK\r\n"),
8680 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8681 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068682 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358683 };
8684
[email protected]31a2bfe2010-02-09 08:03:398685 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8686 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078687 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358688
[email protected]49639fa2011-12-20 23:22:418689 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358690
[email protected]49639fa2011-12-20 23:22:418691 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:358692 EXPECT_EQ(ERR_IO_PENDING, rv);
8693
8694 rv = callback.WaitForResult();
8695 EXPECT_EQ(OK, rv);
8696
8697 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508698 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:358699
[email protected]029c83b62013-01-24 05:28:208700 LoadTimingInfo load_timing_info;
8701 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8702 TestLoadTimingNotReusedWithPac(load_timing_info,
8703 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8704
[email protected]e0c27be2009-07-15 13:09:358705 std::string response_text;
8706 rv = ReadTransaction(trans.get(), &response_text);
8707 EXPECT_EQ(OK, rv);
8708 EXPECT_EQ("Payload", response_text);
8709}
8710
[email protected]23e482282013-06-14 16:08:028711TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278712 HttpRequestInfo request;
8713 request.method = "GET";
bncce36dca22015-04-21 22:11:238714 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278715 request.load_flags = 0;
8716
rdsmith82957ad2015-09-16 19:42:038717 session_deps_.proxy_service =
8718 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518719 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078720 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358721
mmenkee65e7af2015-10-13 17:16:428722 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e0c27be2009-07-15 13:09:358723 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418724 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358725
[email protected]e0c27be2009-07-15 13:09:358726 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8727 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378728 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238729 0x05, // Version
8730 0x01, // Command (CONNECT)
8731 0x00, // Reserved.
8732 0x03, // Address type (DOMAINNAME).
8733 0x0F, // Length of domain (15)
8734 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8735 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:378736 };
8737
[email protected]e0c27be2009-07-15 13:09:358738 const char kSOCKS5OkResponse[] =
8739 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
8740
8741 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238742 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8743 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
8744 arraysize(kSOCKS5OkRequest)),
8745 MockWrite(
8746 "GET / HTTP/1.1\r\n"
8747 "Host: www.example.org\r\n"
8748 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358749
8750 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018751 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8752 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:028753 MockRead("HTTP/1.0 200 OK\r\n"),
8754 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8755 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068756 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028757 };
8758
[email protected]31a2bfe2010-02-09 08:03:398759 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8760 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078761 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028762
[email protected]8ddf8322012-02-23 18:08:068763 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078764 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:028765
[email protected]49639fa2011-12-20 23:22:418766 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028767
[email protected]49639fa2011-12-20 23:22:418768 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:028769 EXPECT_EQ(ERR_IO_PENDING, rv);
8770
8771 rv = callback.WaitForResult();
8772 EXPECT_EQ(OK, rv);
8773
8774 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508775 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:028776
[email protected]029c83b62013-01-24 05:28:208777 LoadTimingInfo load_timing_info;
8778 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8779 TestLoadTimingNotReusedWithPac(load_timing_info,
8780 CONNECT_TIMING_HAS_SSL_TIMES);
8781
[email protected]3cd17242009-06-23 02:59:028782 std::string response_text;
8783 rv = ReadTransaction(trans.get(), &response_text);
8784 EXPECT_EQ(OK, rv);
8785 EXPECT_EQ("Payload", response_text);
8786}
8787
[email protected]448d4ca52012-03-04 04:12:238788namespace {
8789
[email protected]04e5be32009-06-26 20:00:318790// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:068791
8792struct GroupNameTest {
8793 std::string proxy_server;
8794 std::string url;
8795 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:188796 bool ssl;
[email protected]2d731a32010-04-29 01:04:068797};
8798
mmenkee65e7af2015-10-13 17:16:428799scoped_ptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8a0fc822013-06-27 20:52:438800 NextProto next_proto,
[email protected]bb88e1d32013-05-03 23:11:078801 SpdySessionDependencies* session_deps_) {
mmenkee65e7af2015-10-13 17:16:428802 scoped_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:068803
[email protected]30d4c022013-07-18 22:58:168804 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:538805 session->http_server_properties();
bnccacc0992015-03-20 20:22:228806 AlternativeService alternative_service(
bnc4988e432015-03-31 03:06:258807 AlternateProtocolFromNextProto(next_proto), "", 443);
bnc7dc7e1b42015-07-28 14:43:128808 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:228809 http_server_properties->SetAlternativeService(
rchdc7b9052016-03-17 20:51:508810 HostPortPair("host.with.alternate", 80), alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:068811
8812 return session;
8813}
8814
mmenkee65e7af2015-10-13 17:16:428815int GroupNameTransactionHelper(const std::string& url,
8816 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:068817 HttpRequestInfo request;
8818 request.method = "GET";
8819 request.url = GURL(url);
8820 request.load_flags = 0;
8821
[email protected]262eec82013-03-19 21:01:368822 scoped_ptr<HttpTransaction> trans(
mmenkee65e7af2015-10-13 17:16:428823 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
[email protected]cb9bf6ca2011-01-28 13:15:278824
[email protected]49639fa2011-12-20 23:22:418825 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:068826
8827 // We do not complete this request, the dtor will clean the transaction up.
[email protected]49639fa2011-12-20 23:22:418828 return trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d731a32010-04-29 01:04:068829}
8830
[email protected]448d4ca52012-03-04 04:12:238831} // namespace
8832
[email protected]23e482282013-06-14 16:08:028833TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
[email protected]2d731a32010-04-29 01:04:068834 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238835 {
8836 "", // unused
8837 "http://www.example.org/direct",
8838 "www.example.org:80",
8839 false,
8840 },
8841 {
8842 "", // unused
8843 "http://[2001:1418:13:1::25]/direct",
8844 "[2001:1418:13:1::25]:80",
8845 false,
8846 },
[email protected]04e5be32009-06-26 20:00:318847
bncce36dca22015-04-21 22:11:238848 // SSL Tests
8849 {
8850 "", // unused
8851 "https://www.example.org/direct_ssl",
8852 "ssl/www.example.org:443",
8853 true,
8854 },
8855 {
8856 "", // unused
8857 "https://[2001:1418:13:1::25]/direct",
8858 "ssl/[2001:1418:13:1::25]:443",
8859 true,
8860 },
8861 {
8862 "", // unused
8863 "http://host.with.alternate/direct",
8864 "ssl/host.with.alternate:443",
8865 true,
8866 },
[email protected]2d731a32010-04-29 01:04:068867 };
[email protected]2ff8b312010-04-26 22:20:548868
bncf33fb31b2016-01-29 15:22:268869 session_deps_.parse_alternative_services = true;
8870 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]2d731a32010-04-29 01:04:068871
viettrungluue4a8b882014-10-16 06:17:388872 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038873 session_deps_.proxy_service =
8874 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428875 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388876 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]2d731a32010-04-29 01:04:068877
mmenkee65e7af2015-10-13 17:16:428878 HttpNetworkSessionPeer peer(session.get());
[email protected]ab739042011-04-07 15:22:288879 CaptureGroupNameTransportSocketPool* transport_conn_pool =
8880 new CaptureGroupNameTransportSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138881 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348882 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]831e4a32013-11-14 02:14:448883 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8884 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028885 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
8886 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
dchengc7eeda422015-12-26 03:56:488887 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:068888
8889 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428890 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188891 if (tests[i].ssl)
8892 EXPECT_EQ(tests[i].expected_group_name,
8893 ssl_conn_pool->last_group_name_received());
8894 else
8895 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:288896 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:068897 }
[email protected]2d731a32010-04-29 01:04:068898}
8899
[email protected]23e482282013-06-14 16:08:028900TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
[email protected]2d731a32010-04-29 01:04:068901 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238902 {
8903 "http_proxy",
8904 "http://www.example.org/http_proxy_normal",
8905 "www.example.org:80",
8906 false,
8907 },
[email protected]2d731a32010-04-29 01:04:068908
bncce36dca22015-04-21 22:11:238909 // SSL Tests
8910 {
8911 "http_proxy",
8912 "https://www.example.org/http_connect_ssl",
8913 "ssl/www.example.org:443",
8914 true,
8915 },
[email protected]af3490e2010-10-16 21:02:298916
bncce36dca22015-04-21 22:11:238917 {
8918 "http_proxy",
8919 "http://host.with.alternate/direct",
8920 "ssl/host.with.alternate:443",
8921 true,
8922 },
[email protected]45499252013-01-23 17:12:568923
bncce36dca22015-04-21 22:11:238924 {
8925 "http_proxy",
8926 "ftp://ftp.google.com/http_proxy_normal",
8927 "ftp/ftp.google.com:21",
8928 false,
8929 },
[email protected]2d731a32010-04-29 01:04:068930 };
8931
bncf33fb31b2016-01-29 15:22:268932 session_deps_.parse_alternative_services = true;
8933 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]2d731a32010-04-29 01:04:068934
viettrungluue4a8b882014-10-16 06:17:388935 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:038936 session_deps_.proxy_service =
8937 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:428938 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:388939 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]2d731a32010-04-29 01:04:068940
mmenkee65e7af2015-10-13 17:16:428941 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:068942
[email protected]e60e47a2010-07-14 03:37:188943 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:138944 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:348945 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:138946 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:348947 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:028948
[email protected]831e4a32013-11-14 02:14:448949 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
8950 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:028951 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
8952 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchengc7eeda422015-12-26 03:56:488953 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:068954
8955 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:428956 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:188957 if (tests[i].ssl)
8958 EXPECT_EQ(tests[i].expected_group_name,
8959 ssl_conn_pool->last_group_name_received());
8960 else
8961 EXPECT_EQ(tests[i].expected_group_name,
8962 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:068963 }
[email protected]2d731a32010-04-29 01:04:068964}
8965
[email protected]23e482282013-06-14 16:08:028966TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
[email protected]2d731a32010-04-29 01:04:068967 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:238968 {
8969 "socks4://socks_proxy:1080",
8970 "http://www.example.org/socks4_direct",
8971 "socks4/www.example.org:80",
8972 false,
8973 },
8974 {
8975 "socks5://socks_proxy:1080",
8976 "http://www.example.org/socks5_direct",
8977 "socks5/www.example.org:80",
8978 false,
8979 },
[email protected]2d731a32010-04-29 01:04:068980
bncce36dca22015-04-21 22:11:238981 // SSL Tests
8982 {
8983 "socks4://socks_proxy:1080",
8984 "https://www.example.org/socks4_ssl",
8985 "socks4/ssl/www.example.org:443",
8986 true,
8987 },
8988 {
8989 "socks5://socks_proxy:1080",
8990 "https://www.example.org/socks5_ssl",
8991 "socks5/ssl/www.example.org:443",
8992 true,
8993 },
[email protected]af3490e2010-10-16 21:02:298994
bncce36dca22015-04-21 22:11:238995 {
8996 "socks4://socks_proxy:1080",
8997 "http://host.with.alternate/direct",
8998 "socks4/ssl/host.with.alternate:443",
8999 true,
9000 },
[email protected]04e5be32009-06-26 20:00:319001 };
9002
bncf33fb31b2016-01-29 15:22:269003 session_deps_.parse_alternative_services = true;
9004 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]2ff8b312010-04-26 22:20:549005
viettrungluue4a8b882014-10-16 06:17:389006 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:039007 session_deps_.proxy_service =
9008 ProxyService::CreateFixed(tests[i].proxy_server);
mmenkee65e7af2015-10-13 17:16:429009 scoped_ptr<HttpNetworkSession> session(
rdsmithebb50aa2015-11-12 03:44:389010 SetupSessionForGroupNameTests(GetProtocol(), &session_deps_));
[email protected]8b114dd72011-03-25 05:33:029011
mmenkee65e7af2015-10-13 17:16:429012 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:319013
[email protected]e60e47a2010-07-14 03:37:189014 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:139015 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:349016 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:139017 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:349018 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:029019
[email protected]831e4a32013-11-14 02:14:449020 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
9021 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:029022 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
9023 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchengc7eeda422015-12-26 03:56:489024 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:319025
[email protected]262eec82013-03-19 21:01:369026 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509027 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]04e5be32009-06-26 20:00:319028
[email protected]2d731a32010-04-29 01:04:069029 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:429030 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:189031 if (tests[i].ssl)
9032 EXPECT_EQ(tests[i].expected_group_name,
9033 ssl_conn_pool->last_group_name_received());
9034 else
9035 EXPECT_EQ(tests[i].expected_group_name,
9036 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:319037 }
9038}
9039
[email protected]23e482282013-06-14 16:08:029040TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:279041 HttpRequestInfo request;
9042 request.method = "GET";
bncce36dca22015-04-21 22:11:239043 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:279044
rdsmith82957ad2015-09-16 19:42:039045 session_deps_.proxy_service =
9046 ProxyService::CreateFixed("myproxy:70;foobar:80");
[email protected]b59ff372009-07-15 22:04:329047
[email protected]69719062010-01-05 20:09:219048 // This simulates failure resolving all hostnames; that means we will fail
9049 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:079050 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:329051
mmenkee65e7af2015-10-13 17:16:429052 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]9172a982009-06-06 00:30:259053 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419054 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]9172a982009-06-06 00:30:259055
[email protected]49639fa2011-12-20 23:22:419056 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:259057
[email protected]49639fa2011-12-20 23:22:419058 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9172a982009-06-06 00:30:259059 EXPECT_EQ(ERR_IO_PENDING, rv);
9060
[email protected]9172a982009-06-06 00:30:259061 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:019062 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:259063}
9064
[email protected]685af592010-05-11 19:31:249065// Base test to make sure that when the load flags for a request specify to
9066// bypass the cache, the DNS cache is not used.
[email protected]23e482282013-06-14 16:08:029067void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
[email protected]bb88e1d32013-05-03 23:11:079068 int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:279069 // Issue a request, asking to bypass the cache(s).
9070 HttpRequestInfo request;
9071 request.method = "GET";
9072 request.load_flags = load_flags;
bncce36dca22015-04-21 22:11:239073 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:279074
[email protected]a2c2fb92009-07-18 07:31:049075 // Select a host resolver that does caching.
[email protected]bb88e1d32013-05-03 23:11:079076 session_deps_.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:329077
mmenkee65e7af2015-10-13 17:16:429078 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:079079 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419080 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3b9cca42009-06-16 01:08:289081
bncce36dca22015-04-21 22:11:239082 // Warm up the host cache so it has an entry for "www.example.org".
[email protected]3b9cca42009-06-16 01:08:289083 AddressList addrlist;
[email protected]aa22b242011-11-16 18:58:299084 TestCompletionCallback callback;
[email protected]bb88e1d32013-05-03 23:11:079085 int rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:239086 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
9087 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:479088 EXPECT_EQ(ERR_IO_PENDING, rv);
9089 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:289090 EXPECT_EQ(OK, rv);
9091
9092 // Verify that it was added to host cache, by doing a subsequent async lookup
9093 // and confirming it completes synchronously.
[email protected]bb88e1d32013-05-03 23:11:079094 rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:239095 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
9096 DEFAULT_PRIORITY, &addrlist, callback.callback(), NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:329097 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:289098
bncce36dca22015-04-21 22:11:239099 // Inject a failure the next time that "www.example.org" is resolved. This way
[email protected]3b9cca42009-06-16 01:08:289100 // we can tell if the next lookup hit the cache, or the "network".
9101 // (cache --> success, "network" --> failure).
bncce36dca22015-04-21 22:11:239102 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
[email protected]3b9cca42009-06-16 01:08:289103
9104 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
9105 // first read -- this won't be reached as the host resolution will fail first.
[email protected]8ddf8322012-02-23 18:08:069106 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:399107 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079108 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:289109
[email protected]3b9cca42009-06-16 01:08:289110 // Run the request.
[email protected]49639fa2011-12-20 23:22:419111 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:289112 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419113 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:289114
9115 // If we bypassed the cache, we would have gotten a failure while resolving
bncce36dca22015-04-21 22:11:239116 // "www.example.org".
[email protected]3b9cca42009-06-16 01:08:289117 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
9118}
9119
[email protected]685af592010-05-11 19:31:249120// There are multiple load flags that should trigger the host cache bypass.
9121// Test each in isolation:
[email protected]23e482282013-06-14 16:08:029122TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
[email protected]685af592010-05-11 19:31:249123 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
9124}
9125
[email protected]23e482282013-06-14 16:08:029126TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
[email protected]685af592010-05-11 19:31:249127 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
9128}
9129
[email protected]23e482282013-06-14 16:08:029130TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
[email protected]685af592010-05-11 19:31:249131 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
9132}
9133
[email protected]0877e3d2009-10-17 22:29:579134// Make sure we can handle an error when writing the request.
[email protected]23e482282013-06-14 16:08:029135TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:579136 HttpRequestInfo request;
9137 request.method = "GET";
9138 request.url = GURL("http://www.foo.com/");
9139 request.load_flags = 0;
9140
9141 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:069142 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:579143 };
[email protected]31a2bfe2010-02-09 08:03:399144 StaticSocketDataProvider data(NULL, 0,
9145 write_failure, arraysize(write_failure));
[email protected]bb88e1d32013-05-03 23:11:079146 session_deps_.socket_factory->AddSocketDataProvider(&data);
mmenkee65e7af2015-10-13 17:16:429147 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579148
[email protected]49639fa2011-12-20 23:22:419149 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579150
9151 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419152 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579153
[email protected]49639fa2011-12-20 23:22:419154 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579155 EXPECT_EQ(ERR_IO_PENDING, rv);
9156
9157 rv = callback.WaitForResult();
9158 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
ttuttled9dbc652015-09-29 20:00:599159
9160 IPEndPoint endpoint;
9161 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
9162 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:579163}
9164
zmo9528c9f42015-08-04 22:12:089165// Check that a connection closed after the start of the headers finishes ok.
9166TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:579167 HttpRequestInfo request;
9168 request.method = "GET";
9169 request.url = GURL("http://www.foo.com/");
9170 request.load_flags = 0;
9171
9172 MockRead data_reads[] = {
9173 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:069174 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:579175 };
9176
[email protected]31a2bfe2010-02-09 08:03:399177 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079178 session_deps_.socket_factory->AddSocketDataProvider(&data);
mmenkee65e7af2015-10-13 17:16:429179 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579180
[email protected]49639fa2011-12-20 23:22:419181 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579182
9183 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419184 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579185
[email protected]49639fa2011-12-20 23:22:419186 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579187 EXPECT_EQ(ERR_IO_PENDING, rv);
9188
9189 rv = callback.WaitForResult();
zmo9528c9f42015-08-04 22:12:089190 EXPECT_EQ(OK, rv);
9191
9192 const HttpResponseInfo* response = trans->GetResponseInfo();
9193 ASSERT_TRUE(response != NULL);
9194
9195 EXPECT_TRUE(response->headers.get() != NULL);
9196 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9197
9198 std::string response_data;
9199 rv = ReadTransaction(trans.get(), &response_data);
9200 EXPECT_EQ(OK, rv);
9201 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:599202
9203 IPEndPoint endpoint;
9204 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
9205 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:579206}
9207
9208// Make sure that a dropped connection while draining the body for auth
9209// restart does the right thing.
[email protected]23e482282013-06-14 16:08:029210TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:579211 HttpRequestInfo request;
9212 request.method = "GET";
bncce36dca22015-04-21 22:11:239213 request.url = GURL("http://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:579214 request.load_flags = 0;
9215
9216 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239217 MockWrite(
9218 "GET / HTTP/1.1\r\n"
9219 "Host: www.example.org\r\n"
9220 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:579221 };
9222
9223 MockRead data_reads1[] = {
9224 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
9225 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9226 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9227 MockRead("Content-Length: 14\r\n\r\n"),
9228 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:069229 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:579230 };
9231
[email protected]31a2bfe2010-02-09 08:03:399232 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9233 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:079234 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:579235
9236 // After calling trans->RestartWithAuth(), this is the request we should
9237 // be issuing -- the final header line contains the credentials.
9238 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239239 MockWrite(
9240 "GET / HTTP/1.1\r\n"
9241 "Host: www.example.org\r\n"
9242 "Connection: keep-alive\r\n"
9243 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:579244 };
9245
9246 // Lastly, the server responds with the actual content.
9247 MockRead data_reads2[] = {
9248 MockRead("HTTP/1.1 200 OK\r\n"),
9249 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9250 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069251 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:579252 };
9253
[email protected]31a2bfe2010-02-09 08:03:399254 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9255 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:079256 session_deps_.socket_factory->AddSocketDataProvider(&data2);
mmenkee65e7af2015-10-13 17:16:429257 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579258
[email protected]49639fa2011-12-20 23:22:419259 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:579260
[email protected]262eec82013-03-19 21:01:369261 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509262 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509263
[email protected]49639fa2011-12-20 23:22:419264 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579265 EXPECT_EQ(ERR_IO_PENDING, rv);
9266
9267 rv = callback1.WaitForResult();
9268 EXPECT_EQ(OK, rv);
9269
9270 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509271 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049272 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:579273
[email protected]49639fa2011-12-20 23:22:419274 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:579275
[email protected]49639fa2011-12-20 23:22:419276 rv = trans->RestartWithAuth(
9277 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]0877e3d2009-10-17 22:29:579278 EXPECT_EQ(ERR_IO_PENDING, rv);
9279
9280 rv = callback2.WaitForResult();
9281 EXPECT_EQ(OK, rv);
9282
9283 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509284 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:579285 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9286 EXPECT_EQ(100, response->headers->GetContentLength());
9287}
9288
9289// Test HTTPS connections going through a proxy that sends extra data.
[email protected]23e482282013-06-14 16:08:029290TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
rdsmith82957ad2015-09-16 19:42:039291 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]0877e3d2009-10-17 22:29:579292
9293 HttpRequestInfo request;
9294 request.method = "GET";
bncce36dca22015-04-21 22:11:239295 request.url = GURL("https://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:579296 request.load_flags = 0;
9297
9298 MockRead proxy_reads[] = {
9299 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:069300 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:579301 };
9302
[email protected]31a2bfe2010-02-09 08:03:399303 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]8ddf8322012-02-23 18:08:069304 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:579305
[email protected]bb88e1d32013-05-03 23:11:079306 session_deps_.socket_factory->AddSocketDataProvider(&data);
9307 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:579308
[email protected]49639fa2011-12-20 23:22:419309 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579310
[email protected]bb88e1d32013-05-03 23:11:079311 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:579312
mmenkee65e7af2015-10-13 17:16:429313 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579314 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419315 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579316
[email protected]49639fa2011-12-20 23:22:419317 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:579318 EXPECT_EQ(ERR_IO_PENDING, rv);
9319
9320 rv = callback.WaitForResult();
9321 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
9322}
9323
[email protected]23e482282013-06-14 16:08:029324TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:469325 HttpRequestInfo request;
9326 request.method = "GET";
bncce36dca22015-04-21 22:11:239327 request.url = GURL("http://www.example.org/");
[email protected]9492e4a2010-02-24 00:58:469328 request.load_flags = 0;
9329
mmenkee65e7af2015-10-13 17:16:429330 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:279331 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419332 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:279333
[email protected]e22e1362009-11-23 21:31:129334 MockRead data_reads[] = {
9335 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069336 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:129337 };
[email protected]9492e4a2010-02-24 00:58:469338
9339 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079340 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:469341
[email protected]49639fa2011-12-20 23:22:419342 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:469343
[email protected]49639fa2011-12-20 23:22:419344 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:469345 EXPECT_EQ(ERR_IO_PENDING, rv);
9346
9347 EXPECT_EQ(OK, callback.WaitForResult());
9348
9349 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509350 ASSERT_TRUE(response != NULL);
[email protected]9492e4a2010-02-24 00:58:469351
[email protected]90499482013-06-01 00:39:509352 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]9492e4a2010-02-24 00:58:469353 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9354
9355 std::string response_data;
9356 rv = ReadTransaction(trans.get(), &response_data);
[email protected]5543cbb2012-04-20 16:35:239357 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
[email protected]e22e1362009-11-23 21:31:129358}
9359
[email protected]23e482282013-06-14 16:08:029360TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:159361 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:529362 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:149363 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:219364 UploadFileElementReader::ScopedOverridingContentLengthForTests
9365 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:339366
olli.raula6df48b2a2015-11-26 07:40:229367 std::vector<scoped_ptr<UploadElementReader>> element_readers;
9368 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
avibf0746c2015-12-09 19:53:149369 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
9370 std::numeric_limits<uint64_t>::max(), base::Time())));
olli.raula6df48b2a2015-11-26 07:40:229371 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279372
9373 HttpRequestInfo request;
9374 request.method = "POST";
bncce36dca22015-04-21 22:11:239375 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279376 request.upload_data_stream = &upload_data_stream;
9377 request.load_flags = 0;
9378
mmenkee65e7af2015-10-13 17:16:429379 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]329b68b2012-11-14 17:54:279380 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419381 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]95d88ffe2010-02-04 21:25:339382
9383 MockRead data_reads[] = {
9384 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9385 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069386 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:339387 };
[email protected]31a2bfe2010-02-09 08:03:399388 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079389 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:339390
[email protected]49639fa2011-12-20 23:22:419391 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:339392
[email protected]49639fa2011-12-20 23:22:419393 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:339394 EXPECT_EQ(ERR_IO_PENDING, rv);
9395
9396 rv = callback.WaitForResult();
9397 EXPECT_EQ(OK, rv);
9398
9399 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509400 ASSERT_TRUE(response != NULL);
[email protected]95d88ffe2010-02-04 21:25:339401
[email protected]90499482013-06-01 00:39:509402 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]95d88ffe2010-02-04 21:25:339403 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9404
9405 std::string response_data;
9406 rv = ReadTransaction(trans.get(), &response_data);
9407 EXPECT_EQ(OK, rv);
9408 EXPECT_EQ("hello world", response_data);
9409
[email protected]dd3aa792013-07-16 19:10:239410 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:339411}
9412
[email protected]23e482282013-06-14 16:08:029413TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:159414 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:529415 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:369416 std::string temp_file_content("Unreadable file.");
[email protected]e5c2a22e2014-03-06 20:42:309417 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
[email protected]6624b4622010-03-29 19:58:369418 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:119419 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:369420
olli.raula6df48b2a2015-11-26 07:40:229421 std::vector<scoped_ptr<UploadElementReader>> element_readers;
avibf0746c2015-12-09 19:53:149422 element_readers.push_back(make_scoped_ptr(new UploadFileElementReader(
9423 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
9424 std::numeric_limits<uint64_t>::max(), base::Time())));
olli.raula6df48b2a2015-11-26 07:40:229425 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279426
9427 HttpRequestInfo request;
9428 request.method = "POST";
bncce36dca22015-04-21 22:11:239429 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279430 request.upload_data_stream = &upload_data_stream;
9431 request.load_flags = 0;
9432
[email protected]999dd8c2013-11-12 06:45:549433 // If we try to upload an unreadable file, the transaction should fail.
mmenkee65e7af2015-10-13 17:16:429434 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]329b68b2012-11-14 17:54:279435 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419436 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]6624b4622010-03-29 19:58:369437
[email protected]999dd8c2013-11-12 06:45:549438 StaticSocketDataProvider data(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079439 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:369440
[email protected]49639fa2011-12-20 23:22:419441 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:369442
[email protected]49639fa2011-12-20 23:22:419443 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:369444 EXPECT_EQ(ERR_IO_PENDING, rv);
9445
9446 rv = callback.WaitForResult();
[email protected]999dd8c2013-11-12 06:45:549447 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
[email protected]6624b4622010-03-29 19:58:369448
[email protected]dd3aa792013-07-16 19:10:239449 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:369450}
9451
[email protected]02cad5d2013-10-02 08:14:039452TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
9453 class FakeUploadElementReader : public UploadElementReader {
9454 public:
9455 FakeUploadElementReader() {}
dchengb03027d2014-10-21 12:00:209456 ~FakeUploadElementReader() override {}
[email protected]02cad5d2013-10-02 08:14:039457
9458 const CompletionCallback& callback() const { return callback_; }
9459
9460 // UploadElementReader overrides:
dchengb03027d2014-10-21 12:00:209461 int Init(const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039462 callback_ = callback;
9463 return ERR_IO_PENDING;
9464 }
avibf0746c2015-12-09 19:53:149465 uint64_t GetContentLength() const override { return 0; }
9466 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:209467 int Read(IOBuffer* buf,
9468 int buf_length,
9469 const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039470 return ERR_FAILED;
9471 }
9472
9473 private:
9474 CompletionCallback callback_;
9475 };
9476
9477 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
olli.raula6df48b2a2015-11-26 07:40:229478 std::vector<scoped_ptr<UploadElementReader>> element_readers;
9479 element_readers.push_back(make_scoped_ptr(fake_reader));
9480 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:039481
9482 HttpRequestInfo request;
9483 request.method = "POST";
bncce36dca22015-04-21 22:11:239484 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:039485 request.upload_data_stream = &upload_data_stream;
9486 request.load_flags = 0;
9487
mmenkee65e7af2015-10-13 17:16:429488 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02cad5d2013-10-02 08:14:039489 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419490 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02cad5d2013-10-02 08:14:039491
9492 StaticSocketDataProvider data;
9493 session_deps_.socket_factory->AddSocketDataProvider(&data);
9494
9495 TestCompletionCallback callback;
9496 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9497 EXPECT_EQ(ERR_IO_PENDING, rv);
9498 base::MessageLoop::current()->RunUntilIdle();
9499
9500 // Transaction is pending on request body initialization.
9501 ASSERT_FALSE(fake_reader->callback().is_null());
9502
9503 // Return Init()'s result after the transaction gets destroyed.
9504 trans.reset();
9505 fake_reader->callback().Run(OK); // Should not crash.
9506}
9507
[email protected]aeefc9e82010-02-19 16:18:279508// Tests that changes to Auth realms are treated like auth rejections.
[email protected]23e482282013-06-14 16:08:029509TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:279510 HttpRequestInfo request;
9511 request.method = "GET";
bncce36dca22015-04-21 22:11:239512 request.url = GURL("http://www.example.org/");
[email protected]aeefc9e82010-02-19 16:18:279513 request.load_flags = 0;
9514
9515 // First transaction will request a resource and receive a Basic challenge
9516 // with realm="first_realm".
9517 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239518 MockWrite(
9519 "GET / HTTP/1.1\r\n"
9520 "Host: www.example.org\r\n"
9521 "Connection: keep-alive\r\n"
9522 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279523 };
9524 MockRead data_reads1[] = {
9525 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9526 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9527 "\r\n"),
9528 };
9529
9530 // After calling trans->RestartWithAuth(), provide an Authentication header
9531 // for first_realm. The server will reject and provide a challenge with
9532 // second_realm.
9533 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239534 MockWrite(
9535 "GET / HTTP/1.1\r\n"
9536 "Host: www.example.org\r\n"
9537 "Connection: keep-alive\r\n"
9538 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
9539 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279540 };
9541 MockRead data_reads2[] = {
9542 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9543 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
9544 "\r\n"),
9545 };
9546
9547 // This again fails, and goes back to first_realm. Make sure that the
9548 // entry is removed from cache.
9549 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239550 MockWrite(
9551 "GET / HTTP/1.1\r\n"
9552 "Host: www.example.org\r\n"
9553 "Connection: keep-alive\r\n"
9554 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
9555 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279556 };
9557 MockRead data_reads3[] = {
9558 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9559 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9560 "\r\n"),
9561 };
9562
9563 // Try one last time (with the correct password) and get the resource.
9564 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:239565 MockWrite(
9566 "GET / HTTP/1.1\r\n"
9567 "Host: www.example.org\r\n"
9568 "Connection: keep-alive\r\n"
9569 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
9570 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279571 };
9572 MockRead data_reads4[] = {
9573 MockRead("HTTP/1.1 200 OK\r\n"
9574 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:509575 "Content-Length: 5\r\n"
9576 "\r\n"
9577 "hello"),
[email protected]aeefc9e82010-02-19 16:18:279578 };
9579
9580 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9581 data_writes1, arraysize(data_writes1));
9582 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9583 data_writes2, arraysize(data_writes2));
9584 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
9585 data_writes3, arraysize(data_writes3));
9586 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
9587 data_writes4, arraysize(data_writes4));
[email protected]bb88e1d32013-05-03 23:11:079588 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9589 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9590 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9591 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:279592
[email protected]49639fa2011-12-20 23:22:419593 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:279594
mmenkee65e7af2015-10-13 17:16:429595 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0b0bf032010-09-21 18:08:509596 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419597 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509598
[email protected]aeefc9e82010-02-19 16:18:279599 // Issue the first request with Authorize headers. There should be a
9600 // password prompt for first_realm waiting to be filled in after the
9601 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419602 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:279603 EXPECT_EQ(ERR_IO_PENDING, rv);
9604 rv = callback1.WaitForResult();
9605 EXPECT_EQ(OK, rv);
9606 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509607 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049608 const AuthChallengeInfo* challenge = response->auth_challenge.get();
9609 ASSERT_FALSE(challenge == NULL);
9610 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239611 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049612 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199613 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279614
9615 // Issue the second request with an incorrect password. There should be a
9616 // password prompt for second_realm waiting to be filled in after the
9617 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419618 TestCompletionCallback callback2;
9619 rv = trans->RestartWithAuth(
9620 AuthCredentials(kFirst, kBaz), callback2.callback());
[email protected]aeefc9e82010-02-19 16:18:279621 EXPECT_EQ(ERR_IO_PENDING, rv);
9622 rv = callback2.WaitForResult();
9623 EXPECT_EQ(OK, rv);
9624 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509625 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049626 challenge = response->auth_challenge.get();
9627 ASSERT_FALSE(challenge == NULL);
9628 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239629 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049630 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199631 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279632
9633 // Issue the third request with another incorrect password. There should be
9634 // a password prompt for first_realm waiting to be filled in. If the password
9635 // prompt is not present, it indicates that the HttpAuthCacheEntry for
9636 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:419637 TestCompletionCallback callback3;
9638 rv = trans->RestartWithAuth(
9639 AuthCredentials(kSecond, kFou), callback3.callback());
[email protected]aeefc9e82010-02-19 16:18:279640 EXPECT_EQ(ERR_IO_PENDING, rv);
9641 rv = callback3.WaitForResult();
9642 EXPECT_EQ(OK, rv);
9643 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509644 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:049645 challenge = response->auth_challenge.get();
9646 ASSERT_FALSE(challenge == NULL);
9647 EXPECT_FALSE(challenge->is_proxy);
bncce36dca22015-04-21 22:11:239648 EXPECT_EQ("www.example.org:80", challenge->challenger.ToString());
[email protected]79cb5c12011-09-12 13:12:049649 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199650 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279651
9652 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:419653 TestCompletionCallback callback4;
9654 rv = trans->RestartWithAuth(
9655 AuthCredentials(kFirst, kBar), callback4.callback());
[email protected]aeefc9e82010-02-19 16:18:279656 EXPECT_EQ(ERR_IO_PENDING, rv);
9657 rv = callback4.WaitForResult();
9658 EXPECT_EQ(OK, rv);
9659 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:509660 ASSERT_TRUE(response != NULL);
[email protected]aeefc9e82010-02-19 16:18:279661 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9662}
9663
bncc958faa2015-07-31 18:14:529664TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncf33fb31b2016-01-29 15:22:269665 session_deps_.parse_alternative_services = true;
9666 session_deps_.enable_alternative_service_with_different_host = false;
bncc958faa2015-07-31 18:14:529667
9668 std::string alternative_service_http_header =
9669 GetAlternativeServiceHttpHeader();
9670
9671 MockRead data_reads[] = {
9672 MockRead("HTTP/1.1 200 OK\r\n"),
9673 MockRead(alternative_service_http_header.c_str()),
9674 MockRead("\r\n"),
9675 MockRead("hello world"),
9676 MockRead(SYNCHRONOUS, OK),
9677 };
9678
9679 HttpRequestInfo request;
9680 request.method = "GET";
9681 request.url = GURL("http://www.example.org/");
9682 request.load_flags = 0;
9683
9684 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9685
9686 session_deps_.socket_factory->AddSocketDataProvider(&data);
9687
9688 TestCompletionCallback callback;
9689
mmenkee65e7af2015-10-13 17:16:429690 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529691 scoped_ptr<HttpTransaction> trans(
9692 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9693
9694 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9695 EXPECT_EQ(ERR_IO_PENDING, rv);
9696
9697 HostPortPair http_host_port_pair("www.example.org", 80);
9698 HttpServerProperties& http_server_properties =
9699 *session->http_server_properties();
9700 AlternativeServiceVector alternative_service_vector =
9701 http_server_properties.GetAlternativeServices(http_host_port_pair);
9702 EXPECT_TRUE(alternative_service_vector.empty());
9703
9704 EXPECT_EQ(OK, callback.WaitForResult());
9705
9706 const HttpResponseInfo* response = trans->GetResponseInfo();
9707 ASSERT_TRUE(response != NULL);
9708 ASSERT_TRUE(response->headers.get() != NULL);
9709 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9710 EXPECT_FALSE(response->was_fetched_via_spdy);
9711 EXPECT_FALSE(response->was_npn_negotiated);
9712
9713 std::string response_data;
9714 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9715 EXPECT_EQ("hello world", response_data);
9716
9717 alternative_service_vector =
9718 http_server_properties.GetAlternativeServices(http_host_port_pair);
9719 ASSERT_EQ(1u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389720 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529721 alternative_service_vector[0].protocol);
9722 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9723 EXPECT_EQ(443, alternative_service_vector[0].port);
9724}
9725
bnc4f575852015-10-14 18:35:089726TEST_P(HttpNetworkTransactionTest, ClearAlternativeServices) {
bncf33fb31b2016-01-29 15:22:269727 session_deps_.parse_alternative_services = true;
9728 session_deps_.enable_alternative_service_with_different_host = false;
bnc4f575852015-10-14 18:35:089729
9730 // Set an alternative service for origin.
9731 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9732 HttpServerProperties& http_server_properties =
9733 *session->http_server_properties();
9734 HostPortPair http_host_port_pair("www.example.org", 80);
9735 AlternativeService alternative_service(QUIC, "", 80);
9736 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
rchdc7b9052016-03-17 20:51:509737 http_server_properties.SetAlternativeService(http_host_port_pair,
9738 alternative_service, expiration);
bnc4f575852015-10-14 18:35:089739 AlternativeServiceVector alternative_service_vector =
9740 http_server_properties.GetAlternativeServices(http_host_port_pair);
9741 EXPECT_EQ(1u, alternative_service_vector.size());
9742
9743 // Send a clear header.
9744 MockRead data_reads[] = {
9745 MockRead("HTTP/1.1 200 OK\r\n"),
9746 MockRead("Alt-Svc: clear\r\n"),
9747 MockRead("\r\n"),
9748 MockRead("hello world"),
9749 MockRead(SYNCHRONOUS, OK),
9750 };
9751 StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
9752 session_deps_.socket_factory->AddSocketDataProvider(&data);
9753
9754 HttpRequestInfo request;
9755 request.method = "GET";
9756 request.url = GURL("http://www.example.org/");
9757 request.load_flags = 0;
9758
9759 TestCompletionCallback callback;
9760
9761 scoped_ptr<HttpTransaction> trans(
9762 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9763
9764 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9765 EXPECT_EQ(OK, callback.GetResult(rv));
9766
9767 const HttpResponseInfo* response = trans->GetResponseInfo();
9768 ASSERT_TRUE(response != nullptr);
9769 ASSERT_TRUE(response->headers.get() != nullptr);
9770 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9771 EXPECT_FALSE(response->was_fetched_via_spdy);
9772 EXPECT_FALSE(response->was_npn_negotiated);
9773
9774 std::string response_data;
9775 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9776 EXPECT_EQ("hello world", response_data);
9777
9778 alternative_service_vector =
9779 http_server_properties.GetAlternativeServices(http_host_port_pair);
9780 EXPECT_TRUE(alternative_service_vector.empty());
9781}
9782
bncf33fb31b2016-01-29 15:22:269783// Alternative Service headers must be ignored when
9784// |parse_alternative_services| is false.
bnc54ec34b72015-08-26 19:34:569785TEST_P(HttpNetworkTransactionTest, DoNotHonorAlternativeServiceHeader) {
bncf33fb31b2016-01-29 15:22:269786 session_deps_.parse_alternative_services = false;
bnc54ec34b72015-08-26 19:34:569787
9788 std::string alternative_service_http_header =
9789 GetAlternativeServiceHttpHeader();
9790
9791 MockRead data_reads[] = {
9792 MockRead("HTTP/1.1 200 OK\r\n"),
9793 MockRead(alternative_service_http_header.c_str()),
9794 MockRead("\r\n"),
9795 MockRead("hello world"),
9796 MockRead(SYNCHRONOUS, OK),
9797 };
9798
9799 HttpRequestInfo request;
9800 request.method = "GET";
9801 request.url = GURL("http://www.example.org/");
9802 request.load_flags = 0;
9803
9804 StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
9805
9806 session_deps_.socket_factory->AddSocketDataProvider(&data);
9807
9808 TestCompletionCallback callback;
9809
mmenkee65e7af2015-10-13 17:16:429810 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc54ec34b72015-08-26 19:34:569811 scoped_ptr<HttpTransaction> trans(
9812 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9813
9814 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9815 EXPECT_EQ(ERR_IO_PENDING, rv);
9816
9817 HostPortPair http_host_port_pair("www.example.org", 80);
9818 HttpServerProperties& http_server_properties =
9819 *session->http_server_properties();
9820 AlternativeServiceVector alternative_service_vector =
9821 http_server_properties.GetAlternativeServices(http_host_port_pair);
9822 EXPECT_TRUE(alternative_service_vector.empty());
9823
9824 EXPECT_EQ(OK, callback.WaitForResult());
9825
9826 const HttpResponseInfo* response = trans->GetResponseInfo();
9827 ASSERT_TRUE(response != nullptr);
9828 ASSERT_TRUE(response->headers.get() != nullptr);
9829 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9830 EXPECT_FALSE(response->was_fetched_via_spdy);
9831 EXPECT_FALSE(response->was_npn_negotiated);
9832
9833 std::string response_data;
9834 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9835 EXPECT_EQ("hello world", response_data);
9836
9837 alternative_service_vector =
9838 http_server_properties.GetAlternativeServices(http_host_port_pair);
9839 EXPECT_TRUE(alternative_service_vector.empty());
9840}
9841
bncc958faa2015-07-31 18:14:529842TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) {
bncf33fb31b2016-01-29 15:22:269843 session_deps_.parse_alternative_services = true;
9844 session_deps_.enable_alternative_service_with_different_host = false;
bncc958faa2015-07-31 18:14:529845
9846 MockRead data_reads[] = {
9847 MockRead("HTTP/1.1 200 OK\r\n"),
9848 MockRead("Alt-Svc: "),
9849 MockRead(GetAlternateProtocolFromParam()),
bnc44858c82015-10-16 11:57:219850 MockRead("=\"www.example.com:443\";p=\"1.0\","),
bnc3f0118e2016-02-02 15:42:229851 MockRead(GetAlternateProtocolFromParam()),
9852 MockRead("=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:529853 MockRead("hello world"),
9854 MockRead(SYNCHRONOUS, OK),
9855 };
9856
9857 HttpRequestInfo request;
9858 request.method = "GET";
9859 request.url = GURL("http://www.example.org/");
9860 request.load_flags = 0;
9861
9862 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9863
9864 session_deps_.socket_factory->AddSocketDataProvider(&data);
9865
9866 TestCompletionCallback callback;
9867
mmenkee65e7af2015-10-13 17:16:429868 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:529869 scoped_ptr<HttpTransaction> trans(
9870 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9871
9872 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9873 EXPECT_EQ(ERR_IO_PENDING, rv);
9874
9875 HostPortPair http_host_port_pair("www.example.org", 80);
9876 HttpServerProperties& http_server_properties =
9877 *session->http_server_properties();
9878 AlternativeServiceVector alternative_service_vector =
9879 http_server_properties.GetAlternativeServices(http_host_port_pair);
9880 EXPECT_TRUE(alternative_service_vector.empty());
9881
9882 EXPECT_EQ(OK, callback.WaitForResult());
9883
9884 const HttpResponseInfo* response = trans->GetResponseInfo();
9885 ASSERT_TRUE(response != NULL);
9886 ASSERT_TRUE(response->headers.get() != NULL);
9887 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9888 EXPECT_FALSE(response->was_fetched_via_spdy);
9889 EXPECT_FALSE(response->was_npn_negotiated);
9890
9891 std::string response_data;
9892 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9893 EXPECT_EQ("hello world", response_data);
9894
9895 alternative_service_vector =
9896 http_server_properties.GetAlternativeServices(http_host_port_pair);
9897 ASSERT_EQ(2u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:389898 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:529899 alternative_service_vector[0].protocol);
9900 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
9901 EXPECT_EQ(443, alternative_service_vector[0].port);
bnc3f0118e2016-02-02 15:42:229902 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
9903 alternative_service_vector[1].protocol);
bncc958faa2015-07-31 18:14:529904 EXPECT_EQ("www.example.org", alternative_service_vector[1].host);
9905 EXPECT_EQ(1234, alternative_service_vector[1].port);
9906}
9907
bncf33fb31b2016-01-29 15:22:269908// Alternate Protocol headers must be honored even if
9909// |parse_alternative_services| is false.
[email protected]23e482282013-06-14 16:08:029910TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
bncf33fb31b2016-01-29 15:22:269911 session_deps_.parse_alternative_services = false;
[email protected]a2cb8122010-03-10 17:22:429912
[email protected]8a0fc822013-06-27 20:52:439913 std::string alternate_protocol_http_header =
9914 GetAlternateProtocolHttpHeader();
9915
[email protected]564b4912010-03-09 16:30:429916 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:529917 MockRead("HTTP/1.1 200 OK\r\n"),
9918 MockRead(alternate_protocol_http_header.c_str()),
9919 MockRead("\r\n"),
9920 MockRead("hello world"),
9921 MockRead(SYNCHRONOUS, OK),
[email protected]564b4912010-03-09 16:30:429922 };
9923
9924 HttpRequestInfo request;
9925 request.method = "GET";
bncce36dca22015-04-21 22:11:239926 request.url = GURL("http://www.example.org/");
[email protected]564b4912010-03-09 16:30:429927 request.load_flags = 0;
9928
9929 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9930
[email protected]bb88e1d32013-05-03 23:11:079931 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]564b4912010-03-09 16:30:429932
[email protected]49639fa2011-12-20 23:22:419933 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:429934
mmenkee65e7af2015-10-13 17:16:429935 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:369936 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509937 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]564b4912010-03-09 16:30:429938
[email protected]49639fa2011-12-20 23:22:419939 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:429940 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:539941
bncce36dca22015-04-21 22:11:239942 HostPortPair http_host_port_pair("www.example.org", 80);
[email protected]9801e3702014-03-07 09:33:559943 HttpServerProperties& http_server_properties =
[email protected]17291a022011-10-10 07:32:539944 *session->http_server_properties();
bncd9b132e2015-07-08 05:16:109945 AlternativeServiceVector alternative_service_vector =
9946 http_server_properties.GetAlternativeServices(http_host_port_pair);
9947 EXPECT_TRUE(alternative_service_vector.empty());
[email protected]564b4912010-03-09 16:30:429948
9949 EXPECT_EQ(OK, callback.WaitForResult());
9950
9951 const HttpResponseInfo* response = trans->GetResponseInfo();
9952 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:509953 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]564b4912010-03-09 16:30:429954 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:539955 EXPECT_FALSE(response->was_fetched_via_spdy);
9956 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:429957
9958 std::string response_data;
9959 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9960 EXPECT_EQ("hello world", response_data);
9961
bncd9b132e2015-07-08 05:16:109962 alternative_service_vector =
9963 http_server_properties.GetAlternativeServices(http_host_port_pair);
9964 ASSERT_EQ(1u, alternative_service_vector.size());
9965 EXPECT_EQ(443, alternative_service_vector[0].port);
rdsmithebb50aa2015-11-12 03:44:389966 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncd9b132e2015-07-08 05:16:109967 alternative_service_vector[0].protocol);
[email protected]564b4912010-03-09 16:30:429968}
9969
rch89c6e102015-03-18 18:56:529970TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
rch3f4b8452016-02-23 16:59:329971 session_deps_.parse_alternative_services = false;
bncf33fb31b2016-01-29 15:22:269972 session_deps_.enable_alternative_service_with_different_host = false;
rch89c6e102015-03-18 18:56:529973
9974 MockRead data_reads[] = {
9975 MockRead("HTTP/1.1 200 OK\r\n"),
9976 MockRead("Alternate-Protocol: \r\n\r\n"),
9977 MockRead("hello world"),
9978 MockRead(SYNCHRONOUS, OK),
9979 };
9980
9981 HttpRequestInfo request;
9982 request.method = "GET";
bncce36dca22015-04-21 22:11:239983 request.url = GURL("http://www.example.org/");
rch89c6e102015-03-18 18:56:529984 request.load_flags = 0;
9985
9986 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9987
9988 session_deps_.socket_factory->AddSocketDataProvider(&data);
9989
9990 TestCompletionCallback callback;
9991
mmenkee65e7af2015-10-13 17:16:429992 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rch89c6e102015-03-18 18:56:529993
bncce36dca22015-04-21 22:11:239994 HostPortPair http_host_port_pair("www.example.org", 80);
rch89c6e102015-03-18 18:56:529995 HttpServerProperties& http_server_properties =
9996 *session->http_server_properties();
bnccacc0992015-03-20 20:22:229997 AlternativeService alternative_service(QUIC, "", 80);
bnc7dc7e1b42015-07-28 14:43:129998 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
rchdc7b9052016-03-17 20:51:509999 http_server_properties.SetAlternativeService(http_host_port_pair,
10000 alternative_service, expiration);
bnccacc0992015-03-20 20:22:2210001
bncd9b132e2015-07-08 05:16:1010002 AlternativeServiceVector alternative_service_vector =
10003 http_server_properties.GetAlternativeServices(http_host_port_pair);
10004 ASSERT_EQ(1u, alternative_service_vector.size());
10005 EXPECT_EQ(QUIC, alternative_service_vector[0].protocol);
rch89c6e102015-03-18 18:56:5210006
10007 scoped_ptr<HttpTransaction> trans(
10008 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10009
10010 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10011 EXPECT_EQ(ERR_IO_PENDING, rv);
10012
10013 EXPECT_EQ(OK, callback.WaitForResult());
10014
10015 const HttpResponseInfo* response = trans->GetResponseInfo();
10016 ASSERT_TRUE(response != NULL);
10017 ASSERT_TRUE(response->headers.get() != NULL);
10018 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10019 EXPECT_FALSE(response->was_fetched_via_spdy);
10020 EXPECT_FALSE(response->was_npn_negotiated);
10021
10022 std::string response_data;
10023 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10024 EXPECT_EQ("hello world", response_data);
10025
bncd9b132e2015-07-08 05:16:1010026 alternative_service_vector =
10027 http_server_properties.GetAlternativeServices(http_host_port_pair);
10028 EXPECT_TRUE(alternative_service_vector.empty());
rch89c6e102015-03-18 18:56:5210029}
10030
bncf33fb31b2016-01-29 15:22:2610031// When |session_deps_.parse_alternative_services = true| and the response has
10032// an Alt-Svc header, then the Alternate-Protocol header is not parsed.
bncc958faa2015-07-31 18:14:5210033TEST_P(HttpNetworkTransactionTest, AltSvcOverwritesAlternateProtocol) {
bncf33fb31b2016-01-29 15:22:2610034 session_deps_.parse_alternative_services = true;
10035 session_deps_.enable_alternative_service_with_different_host = false;
bncc958faa2015-07-31 18:14:5210036
10037 std::string alternative_service_http_header =
10038 GetAlternativeServiceHttpHeader();
10039 std::string alternate_protocol_http_header = GetAlternateProtocolHttpHeader();
10040
10041 MockRead data_reads[] = {
10042 MockRead("HTTP/1.1 200 OK\r\n"),
10043 MockRead(alternative_service_http_header.c_str()),
10044 MockRead(alternate_protocol_http_header.c_str()),
10045 MockRead("\r\n"),
10046 MockRead("hello world"),
10047 MockRead(SYNCHRONOUS, OK),
10048 };
10049
10050 HttpRequestInfo request;
10051 request.method = "GET";
10052 request.url = GURL("http://www.example.org/");
10053 request.load_flags = 0;
10054
10055 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10056
10057 session_deps_.socket_factory->AddSocketDataProvider(&data);
10058
10059 TestCompletionCallback callback;
10060
mmenkee65e7af2015-10-13 17:16:4210061 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bncc958faa2015-07-31 18:14:5210062 scoped_ptr<HttpTransaction> trans(
10063 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10064
10065 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10066 EXPECT_EQ(ERR_IO_PENDING, rv);
10067
10068 HostPortPair http_host_port_pair("www.example.org", 80);
10069 HttpServerProperties& http_server_properties =
10070 *session->http_server_properties();
10071 AlternativeServiceVector alternative_service_vector =
10072 http_server_properties.GetAlternativeServices(http_host_port_pair);
10073 EXPECT_TRUE(alternative_service_vector.empty());
10074
10075 EXPECT_EQ(OK, callback.WaitForResult());
10076
10077 const HttpResponseInfo* response = trans->GetResponseInfo();
10078 ASSERT_TRUE(response != NULL);
10079 ASSERT_TRUE(response->headers.get() != NULL);
10080 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10081 EXPECT_FALSE(response->was_fetched_via_spdy);
10082 EXPECT_FALSE(response->was_npn_negotiated);
10083
10084 std::string response_data;
10085 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10086 EXPECT_EQ("hello world", response_data);
10087
10088 alternative_service_vector =
10089 http_server_properties.GetAlternativeServices(http_host_port_pair);
10090 ASSERT_EQ(1u, alternative_service_vector.size());
rdsmithebb50aa2015-11-12 03:44:3810091 EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
bncc958faa2015-07-31 18:14:5210092 alternative_service_vector[0].protocol);
10093 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
10094 EXPECT_EQ(443, alternative_service_vector[0].port);
10095}
10096
bncf33fb31b2016-01-29 15:22:2610097// When |enable_alternative_service_with_different_host| is false, do not
10098// observe alternative service entries that point to a different host.
bnc54ec34b72015-08-26 19:34:5610099TEST_P(HttpNetworkTransactionTest, DisableAlternativeServiceToDifferentHost) {
bncf33fb31b2016-01-29 15:22:2610100 session_deps_.parse_alternative_services = true;
10101 session_deps_.enable_alternative_service_with_different_host = false;
bnc54ec34b72015-08-26 19:34:5610102
10103 HttpRequestInfo request;
10104 request.method = "GET";
10105 request.url = GURL("http://www.example.org/");
10106 request.load_flags = 0;
10107
10108 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
10109 StaticSocketDataProvider first_data;
10110 first_data.set_connect_data(mock_connect);
10111 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
10112
10113 MockRead data_reads[] = {
10114 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
10115 MockRead(ASYNC, OK),
10116 };
10117 StaticSocketDataProvider second_data(data_reads, arraysize(data_reads),
10118 nullptr, 0);
10119 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
10120
mmenkee65e7af2015-10-13 17:16:4210121 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc54ec34b72015-08-26 19:34:5610122
10123 base::WeakPtr<HttpServerProperties> http_server_properties =
10124 session->http_server_properties();
10125 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810126 AlternateProtocolFromNextProto(GetProtocol()), "different.example.org",
10127 80);
bnc54ec34b72015-08-26 19:34:5610128 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10129 http_server_properties->SetAlternativeService(
rchdc7b9052016-03-17 20:51:5010130 HostPortPair::FromURL(request.url), alternative_service, expiration);
bnc54ec34b72015-08-26 19:34:5610131
10132 scoped_ptr<HttpTransaction> trans(
10133 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10134 TestCompletionCallback callback;
10135
10136 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10137 // The connetion to origin was refused, and the alternative service should not
10138 // be used (even though mock data are there), therefore the request should
10139 // fail.
10140 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.GetResult(rv));
10141}
10142
zhongyi48704c182015-12-07 07:52:0210143TEST_P(HttpNetworkTransactionTest, IdentifyQuicBroken) {
10144 HostPortPair origin("origin.example.org", 443);
10145 HostPortPair alternative("alternative.example.org", 443);
10146 std::string origin_url = "https://origin.example.org:443";
10147 std::string alternative_url = "https://alternative.example.org:443";
10148
10149 // Negotiate HTTP/1.1 with alternative.example.org.
10150 SSLSocketDataProvider ssl(ASYNC, OK);
10151 ssl.SetNextProto(kProtoHTTP11);
10152 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10153
10154 // HTTP/1.1 data for request.
10155 MockWrite http_writes[] = {
10156 MockWrite("GET / HTTP/1.1\r\n"
10157 "Host: alternative.example.org\r\n"
10158 "Connection: keep-alive\r\n\r\n"),
10159 };
10160
10161 MockRead http_reads[] = {
10162 MockRead("HTTP/1.1 200 OK\r\n"
10163 "Content-Type: text/html; charset=iso-8859-1\r\n"
10164 "Content-Length: 40\r\n\r\n"
10165 "first HTTP/1.1 response from alternative"),
10166 };
10167 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
10168 http_writes, arraysize(http_writes));
10169 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
10170
10171 StaticSocketDataProvider data_refused;
10172 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
10173 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
10174
10175 // Set up a QUIC alternative service for origin.
bncf33fb31b2016-01-29 15:22:2610176 session_deps_.parse_alternative_services = true;
10177 session_deps_.enable_alternative_service_with_different_host = false;
zhongyi48704c182015-12-07 07:52:0210178 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10179 base::WeakPtr<HttpServerProperties> http_server_properties =
10180 session->http_server_properties();
10181 AlternativeService alternative_service(QUIC, alternative);
10182 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10183 http_server_properties->SetAlternativeService(origin, alternative_service,
rchdc7b9052016-03-17 20:51:5010184 expiration);
zhongyi48704c182015-12-07 07:52:0210185 // Mark the QUIC alternative service as broken.
10186 http_server_properties->MarkAlternativeServiceBroken(alternative_service);
10187
10188 scoped_ptr<HttpTransaction> trans(
10189 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10190 HttpRequestInfo request;
10191 request.method = "GET";
10192 request.url = GURL(origin_url);
10193 request.load_flags = 0;
10194 TestCompletionCallback callback;
10195 NetErrorDetails details;
10196 EXPECT_FALSE(details.quic_broken);
10197
10198 trans->Start(&request, callback.callback(), BoundNetLog());
10199 trans->PopulateNetErrorDetails(&details);
10200 EXPECT_TRUE(details.quic_broken);
10201}
10202
10203TEST_P(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
10204 HostPortPair origin("origin.example.org", 443);
10205 HostPortPair alternative1("alternative1.example.org", 443);
10206 HostPortPair alternative2("alternative2.example.org", 443);
10207 std::string origin_url = "https://origin.example.org:443";
10208 std::string alternative_url1 = "https://alternative1.example.org:443";
10209 std::string alternative_url2 = "https://alternative2.example.org:443";
10210
10211 // Negotiate HTTP/1.1 with alternative1.example.org.
10212 SSLSocketDataProvider ssl(ASYNC, OK);
10213 ssl.SetNextProto(kProtoHTTP11);
10214 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10215
10216 // HTTP/1.1 data for request.
10217 MockWrite http_writes[] = {
10218 MockWrite("GET / HTTP/1.1\r\n"
10219 "Host: alternative1.example.org\r\n"
10220 "Connection: keep-alive\r\n\r\n"),
10221 };
10222
10223 MockRead http_reads[] = {
10224 MockRead("HTTP/1.1 200 OK\r\n"
10225 "Content-Type: text/html; charset=iso-8859-1\r\n"
10226 "Content-Length: 40\r\n\r\n"
10227 "first HTTP/1.1 response from alternative1"),
10228 };
10229 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
10230 http_writes, arraysize(http_writes));
10231 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
10232
10233 StaticSocketDataProvider data_refused;
10234 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
10235 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
10236
bncf33fb31b2016-01-29 15:22:2610237 session_deps_.parse_alternative_services = true;
10238 session_deps_.enable_alternative_service_with_different_host = true;
zhongyi48704c182015-12-07 07:52:0210239 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10240 base::WeakPtr<HttpServerProperties> http_server_properties =
10241 session->http_server_properties();
10242
10243 // Set up two QUIC alternative services for origin.
10244 AlternativeServiceInfoVector alternative_service_info_vector;
10245 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10246
10247 AlternativeService alternative_service1(QUIC, alternative1);
rchdc7b9052016-03-17 20:51:5010248 AlternativeServiceInfo alternative_service_info1(alternative_service1,
zhongyi48704c182015-12-07 07:52:0210249 expiration);
10250 alternative_service_info_vector.push_back(alternative_service_info1);
10251 AlternativeService alternative_service2(QUIC, alternative2);
rchdc7b9052016-03-17 20:51:5010252 AlternativeServiceInfo alternative_service_info2(alternative_service2,
zhongyi48704c182015-12-07 07:52:0210253 expiration);
10254 alternative_service_info_vector.push_back(alternative_service_info2);
10255
10256 http_server_properties->SetAlternativeServices(
10257 origin, alternative_service_info_vector);
10258
10259 // Mark one of the QUIC alternative service as broken.
10260 http_server_properties->MarkAlternativeServiceBroken(alternative_service1);
10261
10262 const AlternativeServiceVector alternative_service_vector =
10263 http_server_properties->GetAlternativeServices(origin);
10264
10265 scoped_ptr<HttpTransaction> trans(
10266 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10267 HttpRequestInfo request;
10268 request.method = "GET";
10269 request.url = GURL(origin_url);
10270 request.load_flags = 0;
10271 TestCompletionCallback callback;
10272 NetErrorDetails details;
10273 EXPECT_FALSE(details.quic_broken);
10274
10275 trans->Start(&request, callback.callback(), BoundNetLog());
10276 trans->PopulateNetErrorDetails(&details);
10277 EXPECT_FALSE(details.quic_broken);
10278}
10279
[email protected]23e482282013-06-14 16:08:0210280TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310281 MarkBrokenAlternateProtocolAndFallback) {
bncf33fb31b2016-01-29 15:22:2610282 session_deps_.parse_alternative_services = true;
10283 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]564b4912010-03-09 16:30:4210284
10285 HttpRequestInfo request;
10286 request.method = "GET";
bncce36dca22015-04-21 22:11:2310287 request.url = GURL("http://www.example.org/");
[email protected]564b4912010-03-09 16:30:4210288 request.load_flags = 0;
10289
[email protected]d973e99a2012-02-17 21:02:3610290 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4210291 StaticSocketDataProvider first_data;
10292 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710293 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]564b4912010-03-09 16:30:4210294
10295 MockRead data_reads[] = {
10296 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10297 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610298 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4210299 };
10300 StaticSocketDataProvider second_data(
10301 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710302 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4210303
mmenkee65e7af2015-10-13 17:16:4210304 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4210305
[email protected]30d4c022013-07-18 22:58:1610306 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310307 session->http_server_properties();
bnc8445b3002015-03-13 01:57:0910308 const HostPortPair host_port_pair = HostPortPair::FromURL(request.url);
[email protected]3912662a32011-10-04 00:51:1110309 // Port must be < 1024, or the header will be ignored (since initial port was
10310 // port 80 (another restricted port).
bncd9b132e2015-07-08 05:16:1010311 const AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810312 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bncd9b132e2015-07-08 05:16:1010313 666); // Port is ignored by MockConnect anyway.
bnc7dc7e1b42015-07-28 14:43:1210314 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10315 http_server_properties->SetAlternativeService(
rchdc7b9052016-03-17 20:51:5010316 host_port_pair, alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4210317
[email protected]262eec82013-03-19 21:01:3610318 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010319 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110320 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4210321
[email protected]49639fa2011-12-20 23:22:4110322 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:4210323 EXPECT_EQ(ERR_IO_PENDING, rv);
10324 EXPECT_EQ(OK, callback.WaitForResult());
10325
10326 const HttpResponseInfo* response = trans->GetResponseInfo();
10327 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010328 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]564b4912010-03-09 16:30:4210329 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10330
10331 std::string response_data;
10332 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10333 EXPECT_EQ("hello world", response_data);
10334
bncd9b132e2015-07-08 05:16:1010335 const AlternativeServiceVector alternative_service_vector =
10336 http_server_properties->GetAlternativeServices(host_port_pair);
10337 ASSERT_EQ(1u, alternative_service_vector.size());
10338 EXPECT_EQ(alternative_service, alternative_service_vector[0]);
10339 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
10340 alternative_service_vector[0]));
[email protected]564b4912010-03-09 16:30:4210341}
10342
bnc55ff9da2015-08-19 18:42:3510343// Ensure that we are not allowed to redirect traffic via an alternate protocol
10344// to an unrestricted (port >= 1024) when the original traffic was on a
10345// restricted port (port < 1024). Ensure that we can redirect in all other
10346// cases.
[email protected]23e482282013-06-14 16:08:0210347TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310348 AlternateProtocolPortRestrictedBlocked) {
bncf33fb31b2016-01-29 15:22:2610349 session_deps_.parse_alternative_services = true;
10350 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]3912662a32011-10-04 00:51:1110351
10352 HttpRequestInfo restricted_port_request;
10353 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310354 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1110355 restricted_port_request.load_flags = 0;
10356
[email protected]d973e99a2012-02-17 21:02:3610357 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110358 StaticSocketDataProvider first_data;
10359 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710360 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110361
10362 MockRead data_reads[] = {
10363 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10364 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610365 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110366 };
10367 StaticSocketDataProvider second_data(
10368 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710369 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110370
mmenkee65e7af2015-10-13 17:16:4210371 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110372
[email protected]30d4c022013-07-18 22:58:1610373 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310374 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110375 const int kUnrestrictedAlternatePort = 1024;
bnccacc0992015-03-20 20:22:2210376 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810377 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210378 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210379 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210380 http_server_properties->SetAlternativeService(
10381 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5010382 expiration);
[email protected]3912662a32011-10-04 00:51:1110383
[email protected]262eec82013-03-19 21:01:3610384 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010385 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110386 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110387
[email protected]49639fa2011-12-20 23:22:4110388 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:3610389 &restricted_port_request,
10390 callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110391 EXPECT_EQ(ERR_IO_PENDING, rv);
10392 // Invalid change to unrestricted port should fail.
10393 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
[email protected]c54c6962013-02-01 04:53:1910394}
[email protected]3912662a32011-10-04 00:51:1110395
bnc55ff9da2015-08-19 18:42:3510396// Ensure that we are allowed to redirect traffic via an alternate protocol to
10397// an unrestricted (port >= 1024) when the original traffic was on a restricted
10398// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
[email protected]23e482282013-06-14 16:08:0210399TEST_P(HttpNetworkTransactionTest,
[email protected]c54c6962013-02-01 04:53:1910400 AlternateProtocolPortRestrictedPermitted) {
bncf33fb31b2016-01-29 15:22:2610401 session_deps_.parse_alternative_services = true;
10402 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]bb88e1d32013-05-03 23:11:0710403 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1910404
10405 HttpRequestInfo restricted_port_request;
10406 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310407 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1910408 restricted_port_request.load_flags = 0;
10409
10410 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
10411 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]c54c6962013-02-01 04:53:1910414
10415 MockRead data_reads[] = {
10416 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10417 MockRead("hello world"),
10418 MockRead(ASYNC, OK),
10419 };
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]c54c6962013-02-01 04:53:1910423
mmenkee65e7af2015-10-13 17:16:4210424 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1910425
[email protected]30d4c022013-07-18 22:58:1610426 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]c54c6962013-02-01 04:53:1910427 session->http_server_properties();
10428 const int kUnrestrictedAlternatePort = 1024;
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 kUnrestrictedAlternatePort);
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(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5010435 expiration);
[email protected]c54c6962013-02-01 04:53:1910436
[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]c54c6962013-02-01 04:53:1910439 TestCompletionCallback callback;
10440
10441 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
[email protected]262eec82013-03-19 21:01:3610442 &restricted_port_request,
10443 callback.callback(), BoundNetLog()));
[email protected]c54c6962013-02-01 04:53:1910444 // Change to unrestricted port should succeed.
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 AlternateProtocolPortRestrictedAllowed) {
bncf33fb31b2016-01-29 15:22:2610454 session_deps_.parse_alternative_services = true;
10455 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]3912662a32011-10-04 00:51:1110456
10457 HttpRequestInfo restricted_port_request;
10458 restricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310459 restricted_port_request.url = GURL("http://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1110460 restricted_port_request.load_flags = 0;
10461
[email protected]d973e99a2012-02-17 21:02:3610462 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110463 StaticSocketDataProvider first_data;
10464 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710465 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110466
10467 MockRead data_reads[] = {
10468 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10469 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610470 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110471 };
10472 StaticSocketDataProvider second_data(
10473 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710474 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110475
mmenkee65e7af2015-10-13 17:16:4210476 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110477
[email protected]30d4c022013-07-18 22:58:1610478 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310479 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110480 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210481 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810482 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210483 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210484 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210485 http_server_properties->SetAlternativeService(
10486 HostPortPair::FromURL(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5010487 expiration);
[email protected]3912662a32011-10-04 00:51:1110488
[email protected]262eec82013-03-19 21:01:3610489 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010490 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110491 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110492
[email protected]49639fa2011-12-20 23:22:4110493 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:3610494 &restricted_port_request,
10495 callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110496 EXPECT_EQ(ERR_IO_PENDING, rv);
10497 // Valid change to restricted port should pass.
10498 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110499}
10500
bnc55ff9da2015-08-19 18:42:3510501// Ensure that we are not allowed to redirect traffic via an alternate protocol
10502// to an unrestricted (port >= 1024) when the original traffic was on a
10503// restricted port (port < 1024). Ensure that we can redirect in all other
10504// cases.
[email protected]23e482282013-06-14 16:08:0210505TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310506 AlternateProtocolPortUnrestrictedAllowed1) {
bncf33fb31b2016-01-29 15:22:2610507 session_deps_.parse_alternative_services = true;
10508 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]3912662a32011-10-04 00:51:1110509
10510 HttpRequestInfo unrestricted_port_request;
10511 unrestricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310512 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110513 unrestricted_port_request.load_flags = 0;
10514
[email protected]d973e99a2012-02-17 21:02:3610515 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110516 StaticSocketDataProvider first_data;
10517 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710518 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110519
10520 MockRead data_reads[] = {
10521 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10522 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610523 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110524 };
10525 StaticSocketDataProvider second_data(
10526 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710527 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110528
mmenkee65e7af2015-10-13 17:16:4210529 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110530
[email protected]30d4c022013-07-18 22:58:1610531 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310532 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110533 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210534 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810535 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210536 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210537 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210538 http_server_properties->SetAlternativeService(
10539 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5010540 expiration);
[email protected]3912662a32011-10-04 00:51:1110541
[email protected]262eec82013-03-19 21:01:3610542 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010543 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110544 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110545
[email protected]49639fa2011-12-20 23:22:4110546 int rv = trans->Start(
10547 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110548 EXPECT_EQ(ERR_IO_PENDING, rv);
10549 // Valid change to restricted port should pass.
10550 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110551}
10552
bnc55ff9da2015-08-19 18:42:3510553// Ensure that we are not allowed to redirect traffic via an alternate protocol
10554// to an unrestricted (port >= 1024) when the original traffic was on a
10555// restricted port (port < 1024). Ensure that we can redirect in all other
10556// cases.
[email protected]23e482282013-06-14 16:08:0210557TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310558 AlternateProtocolPortUnrestrictedAllowed2) {
bncf33fb31b2016-01-29 15:22:2610559 session_deps_.parse_alternative_services = true;
10560 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]3912662a32011-10-04 00:51:1110561
10562 HttpRequestInfo unrestricted_port_request;
10563 unrestricted_port_request.method = "GET";
bncce36dca22015-04-21 22:11:2310564 unrestricted_port_request.url = GURL("http://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110565 unrestricted_port_request.load_flags = 0;
10566
[email protected]d973e99a2012-02-17 21:02:3610567 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110568 StaticSocketDataProvider first_data;
10569 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710570 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110571
10572 MockRead data_reads[] = {
10573 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10574 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610575 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110576 };
10577 StaticSocketDataProvider second_data(
10578 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710579 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110580
mmenkee65e7af2015-10-13 17:16:4210581 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110582
[email protected]30d4c022013-07-18 22:58:1610583 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]17291a022011-10-10 07:32:5310584 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2210585 const int kUnrestrictedAlternatePort = 1025;
bnccacc0992015-03-20 20:22:2210586 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810587 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210588 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210589 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210590 http_server_properties->SetAlternativeService(
10591 HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5010592 expiration);
[email protected]3912662a32011-10-04 00:51:1110593
[email protected]262eec82013-03-19 21:01:3610594 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010595 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110596 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110597
[email protected]49639fa2011-12-20 23:22:4110598 int rv = trans->Start(
10599 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:1110600 EXPECT_EQ(ERR_IO_PENDING, rv);
10601 // Valid change to an unrestricted port should pass.
10602 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]3912662a32011-10-04 00:51:1110603}
10604
bnc55ff9da2015-08-19 18:42:3510605// Ensure that we are not allowed to redirect traffic via an alternate protocol
10606// to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
10607// once the alternate protocol request fails.
[email protected]d7599122014-05-24 03:37:2310608TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
bncf33fb31b2016-01-29 15:22:2610609 session_deps_.parse_alternative_services = true;
10610 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]eb6234e2012-01-19 01:50:0210611
10612 HttpRequestInfo request;
10613 request.method = "GET";
bncce36dca22015-04-21 22:11:2310614 request.url = GURL("http://www.example.org/");
[email protected]eb6234e2012-01-19 01:50:0210615 request.load_flags = 0;
10616
10617 // The alternate protocol request will error out before we attempt to connect,
10618 // so only the standard HTTP request will try to connect.
10619 MockRead data_reads[] = {
10620 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10621 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610622 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0210623 };
10624 StaticSocketDataProvider data(
10625 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710626 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0210627
mmenkee65e7af2015-10-13 17:16:4210628 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0210629
[email protected]30d4c022013-07-18 22:58:1610630 base::WeakPtr<HttpServerProperties> http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0210631 session->http_server_properties();
10632 const int kUnsafePort = 7;
bnccacc0992015-03-20 20:22:2210633 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3810634 AlternateProtocolFromNextProto(GetProtocol()), "www.example.org",
bnccacc0992015-03-20 20:22:2210635 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1210636 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210637 http_server_properties->SetAlternativeService(
rchdc7b9052016-03-17 20:51:5010638 HostPortPair::FromURL(request.url), alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0210639
[email protected]262eec82013-03-19 21:01:3610640 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010641 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]eb6234e2012-01-19 01:50:0210642 TestCompletionCallback callback;
10643
10644 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10645 EXPECT_EQ(ERR_IO_PENDING, rv);
10646 // The HTTP request should succeed.
10647 EXPECT_EQ(OK, callback.WaitForResult());
10648
[email protected]eb6234e2012-01-19 01:50:0210649 const HttpResponseInfo* response = trans->GetResponseInfo();
10650 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010651 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]eb6234e2012-01-19 01:50:0210652 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10653
10654 std::string response_data;
10655 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10656 EXPECT_EQ("hello world", response_data);
10657}
10658
[email protected]23e482282013-06-14 16:08:0210659TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
rch3f4b8452016-02-23 16:59:3210660 session_deps_.parse_alternative_services = false;
bncf33fb31b2016-01-29 15:22:2610661 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]2ff8b312010-04-26 22:20:5410662
10663 HttpRequestInfo request;
10664 request.method = "GET";
bncce36dca22015-04-21 22:11:2310665 request.url = GURL("http://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5410666 request.load_flags = 0;
10667
[email protected]8a0fc822013-06-27 20:52:4310668 std::string alternate_protocol_http_header =
10669 GetAlternateProtocolHttpHeader();
10670
[email protected]2ff8b312010-04-26 22:20:5410671 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210672 MockRead("HTTP/1.1 200 OK\r\n"),
10673 MockRead(alternate_protocol_http_header.c_str()),
10674 MockRead("\r\n"),
10675 MockRead("hello world"),
10676 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10677 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5410678
10679 StaticSocketDataProvider first_transaction(
10680 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710681 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2ff8b312010-04-26 22:20:5410682
[email protected]8ddf8322012-02-23 18:08:0610683 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810684 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310685 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10686 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710687 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2ff8b312010-04-26 22:20:5410688
[email protected]cdf8f7e72013-05-23 10:56:4610689 scoped_ptr<SpdyFrame> req(
bnc38dcd392016-02-09 23:19:4910690 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1310691 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]2ff8b312010-04-26 22:20:5410692
[email protected]23e482282013-06-14 16:08:0210693 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10694 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5410695 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310696 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5410697 };
10698
rch8e6c6c42015-05-01 14:05:1310699 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10700 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710701 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5410702
[email protected]d973e99a2012-02-17 21:02:3610703 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510704 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10705 NULL, 0, NULL, 0);
10706 hanging_non_alternate_protocol_socket.set_connect_data(
10707 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710708 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510709 &hanging_non_alternate_protocol_socket);
10710
[email protected]49639fa2011-12-20 23:22:4110711 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5410712
mmenkee65e7af2015-10-13 17:16:4210713 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610714 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010715 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410716
[email protected]49639fa2011-12-20 23:22:4110717 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410718 EXPECT_EQ(ERR_IO_PENDING, rv);
10719 EXPECT_EQ(OK, callback.WaitForResult());
10720
10721 const HttpResponseInfo* response = trans->GetResponseInfo();
10722 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010723 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5410724 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10725
10726 std::string response_data;
10727 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10728 EXPECT_EQ("hello world", response_data);
10729
[email protected]90499482013-06-01 00:39:5010730 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410731
[email protected]49639fa2011-12-20 23:22:4110732 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5410733 EXPECT_EQ(ERR_IO_PENDING, rv);
10734 EXPECT_EQ(OK, callback.WaitForResult());
10735
10736 response = trans->GetResponseInfo();
10737 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010738 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210739 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310740 EXPECT_TRUE(response->was_fetched_via_spdy);
10741 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5410742
10743 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10744 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5410745}
10746
[email protected]23e482282013-06-14 16:08:0210747TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
rch3f4b8452016-02-23 16:59:3210748 session_deps_.parse_alternative_services = false;
bncf33fb31b2016-01-29 15:22:2610749 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]2d6728692011-03-12 01:39:5510750
10751 HttpRequestInfo request;
10752 request.method = "GET";
bncce36dca22015-04-21 22:11:2310753 request.url = GURL("http://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510754 request.load_flags = 0;
10755
[email protected]8a0fc822013-06-27 20:52:4310756 std::string alternate_protocol_http_header =
10757 GetAlternateProtocolHttpHeader();
10758
[email protected]2d6728692011-03-12 01:39:5510759 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210760 MockRead("HTTP/1.1 200 OK\r\n"),
10761 MockRead(alternate_protocol_http_header.c_str()),
10762 MockRead("\r\n"),
10763 MockRead("hello world"),
10764 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10765 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510766 };
10767
10768 StaticSocketDataProvider first_transaction(
10769 data_reads, arraysize(data_reads), NULL, 0);
10770 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
[email protected]bb88e1d32013-05-03 23:11:0710771 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510772
[email protected]d973e99a2012-02-17 21:02:3610773 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
mmenkecc2298e2015-12-07 18:20:1810774 StaticSocketDataProvider hanging_socket1(NULL, 0, NULL, 0);
10775 hanging_socket1.set_connect_data(never_finishing_connect);
[email protected]2d6728692011-03-12 01:39:5510776 // Socket 2 and 3 are the hanging Alternate-Protocol and
10777 // non-Alternate-Protocol jobs from the 2nd transaction.
mmenkecc2298e2015-12-07 18:20:1810778 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
10779
10780 StaticSocketDataProvider hanging_socket2(NULL, 0, NULL, 0);
10781 hanging_socket2.set_connect_data(never_finishing_connect);
10782 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5510783
[email protected]8ddf8322012-02-23 18:08:0610784 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810785 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2310786 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10787 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0710788 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510789
[email protected]cdf8f7e72013-05-23 10:56:4610790 scoped_ptr<SpdyFrame> req1(
bnc38dcd392016-02-09 23:19:4910791 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]cdf8f7e72013-05-23 10:56:4610792 scoped_ptr<SpdyFrame> req2(
bnc38dcd392016-02-09 23:19:4910793 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
[email protected]2d6728692011-03-12 01:39:5510794 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1310795 CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
[email protected]2d6728692011-03-12 01:39:5510796 };
[email protected]23e482282013-06-14 16:08:0210797 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10798 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
10799 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10800 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5510801 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1310802 CreateMockRead(*resp1, 2),
10803 CreateMockRead(*data1, 3),
10804 CreateMockRead(*resp2, 4),
10805 CreateMockRead(*data2, 5),
10806 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5510807 };
10808
rch8e6c6c42015-05-01 14:05:1310809 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10810 arraysize(spdy_writes));
[email protected]2d6728692011-03-12 01:39:5510811 // Socket 4 is the successful Alternate-Protocol for transaction 3.
[email protected]bb88e1d32013-05-03 23:11:0710812 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5510813
10814 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
mmenkecc2298e2015-12-07 18:20:1810815 StaticSocketDataProvider hanging_socket3(NULL, 0, NULL, 0);
10816 hanging_socket3.set_connect_data(never_finishing_connect);
10817 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5510818
mmenkee65e7af2015-10-13 17:16:4210819 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4110820 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5010821 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5510822
[email protected]49639fa2011-12-20 23:22:4110823 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510824 EXPECT_EQ(ERR_IO_PENDING, rv);
10825 EXPECT_EQ(OK, callback1.WaitForResult());
10826
10827 const HttpResponseInfo* response = trans1.GetResponseInfo();
10828 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010829 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510830 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10831
10832 std::string response_data;
10833 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10834 EXPECT_EQ("hello world", response_data);
10835
[email protected]49639fa2011-12-20 23:22:4110836 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5010837 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110838 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510839 EXPECT_EQ(ERR_IO_PENDING, rv);
10840
[email protected]49639fa2011-12-20 23:22:4110841 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5010842 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110843 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510844 EXPECT_EQ(ERR_IO_PENDING, rv);
10845
10846 EXPECT_EQ(OK, callback2.WaitForResult());
10847 EXPECT_EQ(OK, callback3.WaitForResult());
10848
10849 response = trans2.GetResponseInfo();
10850 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010851 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210852 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5510853 EXPECT_TRUE(response->was_fetched_via_spdy);
10854 EXPECT_TRUE(response->was_npn_negotiated);
10855 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10856 EXPECT_EQ("hello!", response_data);
10857
10858 response = trans3.GetResponseInfo();
10859 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010860 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0210861 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5510862 EXPECT_TRUE(response->was_fetched_via_spdy);
10863 EXPECT_TRUE(response->was_npn_negotiated);
10864 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
10865 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5510866}
10867
[email protected]23e482282013-06-14 16:08:0210868TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
rch3f4b8452016-02-23 16:59:3210869 session_deps_.parse_alternative_services = false;
bncf33fb31b2016-01-29 15:22:2610870 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]2d6728692011-03-12 01:39:5510871
10872 HttpRequestInfo request;
10873 request.method = "GET";
bncce36dca22015-04-21 22:11:2310874 request.url = GURL("http://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510875 request.load_flags = 0;
10876
[email protected]8a0fc822013-06-27 20:52:4310877 std::string alternate_protocol_http_header =
10878 GetAlternateProtocolHttpHeader();
10879
[email protected]2d6728692011-03-12 01:39:5510880 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210881 MockRead("HTTP/1.1 200 OK\r\n"),
10882 MockRead(alternate_protocol_http_header.c_str()),
10883 MockRead("\r\n"),
10884 MockRead("hello world"),
10885 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10886 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510887 };
10888
10889 StaticSocketDataProvider first_transaction(
10890 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710891 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510892
[email protected]8ddf8322012-02-23 18:08:0610893 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3810894 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0710895 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510896
[email protected]d973e99a2012-02-17 21:02:3610897 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510898 StaticSocketDataProvider hanging_alternate_protocol_socket(
10899 NULL, 0, NULL, 0);
10900 hanging_alternate_protocol_socket.set_connect_data(
10901 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710902 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510903 &hanging_alternate_protocol_socket);
10904
10905 // 2nd request is just a copy of the first one, over HTTP again.
mmenkecc2298e2015-12-07 18:20:1810906 StaticSocketDataProvider second_transaction(data_reads, arraysize(data_reads),
10907 NULL, 0);
10908 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
[email protected]2d6728692011-03-12 01:39:5510909
[email protected]49639fa2011-12-20 23:22:4110910 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5510911
mmenkee65e7af2015-10-13 17:16:4210912 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3610913 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010914 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510915
[email protected]49639fa2011-12-20 23:22:4110916 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510917 EXPECT_EQ(ERR_IO_PENDING, rv);
10918 EXPECT_EQ(OK, callback.WaitForResult());
10919
10920 const HttpResponseInfo* response = trans->GetResponseInfo();
10921 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010922 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510923 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10924
10925 std::string response_data;
10926 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10927 EXPECT_EQ("hello world", response_data);
10928
[email protected]90499482013-06-01 00:39:5010929 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510930
[email protected]49639fa2011-12-20 23:22:4110931 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:5510932 EXPECT_EQ(ERR_IO_PENDING, rv);
10933 EXPECT_EQ(OK, callback.WaitForResult());
10934
10935 response = trans->GetResponseInfo();
10936 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5010937 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2d6728692011-03-12 01:39:5510938 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10939 EXPECT_FALSE(response->was_fetched_via_spdy);
10940 EXPECT_FALSE(response->was_npn_negotiated);
10941
10942 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
10943 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5510944}
10945
[email protected]631f1322010-04-30 17:59:1110946class CapturingProxyResolver : public ProxyResolver {
10947 public:
sammce90c9212015-05-27 23:43:3510948 CapturingProxyResolver() {}
dchengb03027d2014-10-21 12:00:2010949 ~CapturingProxyResolver() override {}
[email protected]631f1322010-04-30 17:59:1110950
dchengb03027d2014-10-21 12:00:2010951 int GetProxyForURL(const GURL& url,
10952 ProxyInfo* results,
10953 const CompletionCallback& callback,
eroman9c8f4242016-02-29 21:16:5410954 RequestHandle* request,
dchengb03027d2014-10-21 12:00:2010955 const BoundNetLog& net_log) override {
[email protected]fae7669f2010-08-02 21:49:4010956 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
10957 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:4210958 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:1110959 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:4210960 return OK;
[email protected]631f1322010-04-30 17:59:1110961 }
10962
eroman9c8f4242016-02-29 21:16:5410963 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
10964
10965 LoadState GetLoadState(RequestHandle request) const override {
10966 NOTREACHED();
10967 return LOAD_STATE_IDLE;
10968 }
10969
[email protected]24476402010-07-20 20:55:1710970 const std::vector<GURL>& resolved() const { return resolved_; }
10971
10972 private:
[email protected]631f1322010-04-30 17:59:1110973 std::vector<GURL> resolved_;
10974
10975 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
10976};
10977
sammce64b2362015-04-29 03:50:2310978class CapturingProxyResolverFactory : public ProxyResolverFactory {
10979 public:
10980 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
10981 : ProxyResolverFactory(false), resolver_(resolver) {}
10982
10983 int CreateProxyResolver(
10984 const scoped_refptr<ProxyResolverScriptData>& pac_script,
10985 scoped_ptr<ProxyResolver>* resolver,
10986 const net::CompletionCallback& callback,
10987 scoped_ptr<Request>* request) override {
10988 resolver->reset(new ForwardingProxyResolver(resolver_));
10989 return OK;
10990 }
10991
10992 private:
10993 ProxyResolver* resolver_;
10994};
10995
[email protected]23e482282013-06-14 16:08:0210996TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2310997 UseAlternateProtocolForTunneledNpnSpdy) {
rch3f4b8452016-02-23 16:59:3210998 session_deps_.parse_alternative_services = false;
bncf33fb31b2016-01-29 15:22:2610999 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]631f1322010-04-30 17:59:1111000
11001 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4211002 proxy_config.set_auto_detect(true);
11003 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1111004
sammc5dd160c2015-04-02 02:43:1311005 CapturingProxyResolver capturing_proxy_resolver;
[email protected]bb88e1d32013-05-03 23:11:0711006 session_deps_.proxy_service.reset(new ProxyService(
csharrisonb7e3a082015-09-22 19:13:0411007 make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)),
sammc5dd160c2015-04-02 02:43:1311008 make_scoped_ptr(
sammce64b2362015-04-29 03:50:2311009 new CapturingProxyResolverFactory(&capturing_proxy_resolver)),
[email protected]66761b952010-06-25 21:30:3811010 NULL));
vishal.b62985ca92015-04-17 08:45:5111011 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711012 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1111013
11014 HttpRequestInfo request;
11015 request.method = "GET";
bncce36dca22015-04-21 22:11:2311016 request.url = GURL("http://www.example.org/");
[email protected]631f1322010-04-30 17:59:1111017 request.load_flags = 0;
11018
[email protected]8a0fc822013-06-27 20:52:4311019 std::string alternate_protocol_http_header =
11020 GetAlternateProtocolHttpHeader();
11021
[email protected]631f1322010-04-30 17:59:1111022 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211023 MockRead("HTTP/1.1 200 OK\r\n"),
11024 MockRead(alternate_protocol_http_header.c_str()),
11025 MockRead("\r\n"),
11026 MockRead("hello world"),
11027 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
11028 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1111029 };
11030
11031 StaticSocketDataProvider first_transaction(
11032 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0711033 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]631f1322010-04-30 17:59:1111034
[email protected]8ddf8322012-02-23 18:08:0611035 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811036 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2311037 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11038 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0711039 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]631f1322010-04-30 17:59:1111040
[email protected]cdf8f7e72013-05-23 10:56:4611041 scoped_ptr<SpdyFrame> req(
bnc38dcd392016-02-09 23:19:4911042 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]631f1322010-04-30 17:59:1111043 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1311044 MockWrite(ASYNC, 0,
11045 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711046 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1311047 "Proxy-Connection: keep-alive\r\n\r\n"),
11048 CreateMockWrite(*req, 2),
[email protected]631f1322010-04-30 17:59:1111049 };
11050
[email protected]d911f1b2010-05-05 22:39:4211051 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
11052
[email protected]23e482282013-06-14 16:08:0211053 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11054 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:1111055 MockRead spdy_reads[] = {
mmenkee24011922015-12-17 22:12:5911056 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(*resp.get(), 3),
11057 CreateMockRead(*data.get(), 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1111058 };
11059
rch8e6c6c42015-05-01 14:05:1311060 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11061 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711062 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1111063
[email protected]d973e99a2012-02-17 21:02:3611064 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5511065 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
11066 NULL, 0, NULL, 0);
11067 hanging_non_alternate_protocol_socket.set_connect_data(
11068 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0711069 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5511070 &hanging_non_alternate_protocol_socket);
11071
[email protected]49639fa2011-12-20 23:22:4111072 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1111073
mmenkee65e7af2015-10-13 17:16:4211074 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3611075 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011076 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1111077
[email protected]49639fa2011-12-20 23:22:4111078 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:1111079 EXPECT_EQ(ERR_IO_PENDING, rv);
11080 EXPECT_EQ(OK, callback.WaitForResult());
11081
11082 const HttpResponseInfo* response = trans->GetResponseInfo();
11083 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011084 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]631f1322010-04-30 17:59:1111085 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5311086 EXPECT_FALSE(response->was_fetched_via_spdy);
11087 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:1111088
11089 std::string response_data;
11090 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11091 EXPECT_EQ("hello world", response_data);
11092
[email protected]90499482013-06-01 00:39:5011093 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1111094
[email protected]49639fa2011-12-20 23:22:4111095 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:1111096 EXPECT_EQ(ERR_IO_PENDING, rv);
11097 EXPECT_EQ(OK, callback.WaitForResult());
11098
11099 response = trans->GetResponseInfo();
11100 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011101 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0211102 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5311103 EXPECT_TRUE(response->was_fetched_via_spdy);
11104 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:1111105
11106 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11107 EXPECT_EQ("hello!", response_data);
sammc5dd160c2015-04-02 02:43:1311108 ASSERT_EQ(3u, capturing_proxy_resolver.resolved().size());
bncce36dca22015-04-21 22:11:2311109 EXPECT_EQ("http://www.example.org/",
sammc5dd160c2015-04-02 02:43:1311110 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2311111 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1311112 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1111113
[email protected]029c83b62013-01-24 05:28:2011114 LoadTimingInfo load_timing_info;
11115 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11116 TestLoadTimingNotReusedWithPac(load_timing_info,
11117 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1111118}
[email protected]631f1322010-04-30 17:59:1111119
[email protected]23e482282013-06-14 16:08:0211120TEST_P(HttpNetworkTransactionTest,
[email protected]2ff8b312010-04-26 22:20:5411121 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
rch3f4b8452016-02-23 16:59:3211122 session_deps_.parse_alternative_services = false;
bncf33fb31b2016-01-29 15:22:2611123 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]2ff8b312010-04-26 22:20:5411124
11125 HttpRequestInfo request;
11126 request.method = "GET";
bncce36dca22015-04-21 22:11:2311127 request.url = GURL("http://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5411128 request.load_flags = 0;
11129
[email protected]8a0fc822013-06-27 20:52:4311130 std::string alternate_protocol_http_header =
11131 GetAlternateProtocolHttpHeader();
11132
[email protected]2ff8b312010-04-26 22:20:5411133 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211134 MockRead("HTTP/1.1 200 OK\r\n"),
11135 MockRead(alternate_protocol_http_header.c_str()),
11136 MockRead("\r\n"),
11137 MockRead("hello world"),
11138 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5411139 };
11140
11141 StaticSocketDataProvider first_transaction(
11142 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0711143 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2ff8b312010-04-26 22:20:5411144
[email protected]8ddf8322012-02-23 18:08:0611145 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811146 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2311147 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11148 ASSERT_TRUE(ssl.cert.get());
[email protected]bb88e1d32013-05-03 23:11:0711149 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2ff8b312010-04-26 22:20:5411150
[email protected]cdf8f7e72013-05-23 10:56:4611151 scoped_ptr<SpdyFrame> req(
bnc38dcd392016-02-09 23:19:4911152 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1311153 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]2ff8b312010-04-26 22:20:5411154
[email protected]23e482282013-06-14 16:08:0211155 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11156 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5411157 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1311158 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5411159 };
11160
rch8e6c6c42015-05-01 14:05:1311161 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11162 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711163 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5411164
[email protected]83039bb2011-12-09 18:43:5511165 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5411166
mmenkee65e7af2015-10-13 17:16:4211167 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5411168
[email protected]262eec82013-03-19 21:01:3611169 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011170 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5411171
[email protected]49639fa2011-12-20 23:22:4111172 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5411173 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4111174 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:5411175
11176 const HttpResponseInfo* response = trans->GetResponseInfo();
11177 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011178 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]2ff8b312010-04-26 22:20:5411179 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11180
11181 std::string response_data;
11182 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11183 EXPECT_EQ("hello world", response_data);
11184
11185 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2311186 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4011187 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5311188 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2711189 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:4211190 CreateSecureSpdySession(session.get(), key, BoundNetLog());
[email protected]02b0c342010-09-25 21:09:3811191
[email protected]90499482013-06-01 00:39:5011192 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5411193
[email protected]49639fa2011-12-20 23:22:4111194 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:5411195 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4111196 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:5411197
11198 response = trans->GetResponseInfo();
11199 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011200 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0211201 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5311202 EXPECT_TRUE(response->was_fetched_via_spdy);
11203 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5411204
11205 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11206 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4211207}
11208
[email protected]044de0642010-06-17 10:42:1511209// GenerateAuthToken is a mighty big test.
11210// It tests all permutation of GenerateAuthToken behavior:
11211// - Synchronous and Asynchronous completion.
11212// - OK or error on completion.
11213// - Direct connection, non-authenticating proxy, and authenticating proxy.
11214// - HTTP or HTTPS backend (to include proxy tunneling).
11215// - Non-authenticating and authenticating backend.
11216//
[email protected]fe3b7dc2012-02-03 19:52:0911217// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1511218// problems generating an auth token for an authenticating proxy, we don't
11219// need to test all permutations of the backend server).
11220//
11221// The test proceeds by going over each of the configuration cases, and
11222// potentially running up to three rounds in each of the tests. The TestConfig
11223// specifies both the configuration for the test as well as the expectations
11224// for the results.
[email protected]23e482282013-06-14 16:08:0211225TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5011226 static const char kServer[] = "http://www.example.com";
11227 static const char kSecureServer[] = "https://www.example.com";
11228 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1511229 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
11230
11231 enum AuthTiming {
11232 AUTH_NONE,
11233 AUTH_SYNC,
11234 AUTH_ASYNC,
11235 };
11236
11237 const MockWrite kGet(
11238 "GET / HTTP/1.1\r\n"
11239 "Host: www.example.com\r\n"
11240 "Connection: keep-alive\r\n\r\n");
11241 const MockWrite kGetProxy(
11242 "GET http://www.example.com/ HTTP/1.1\r\n"
11243 "Host: www.example.com\r\n"
11244 "Proxy-Connection: keep-alive\r\n\r\n");
11245 const MockWrite kGetAuth(
11246 "GET / HTTP/1.1\r\n"
11247 "Host: www.example.com\r\n"
11248 "Connection: keep-alive\r\n"
11249 "Authorization: auth_token\r\n\r\n");
11250 const MockWrite kGetProxyAuth(
11251 "GET http://www.example.com/ HTTP/1.1\r\n"
11252 "Host: www.example.com\r\n"
11253 "Proxy-Connection: keep-alive\r\n"
11254 "Proxy-Authorization: auth_token\r\n\r\n");
11255 const MockWrite kGetAuthThroughProxy(
11256 "GET http://www.example.com/ HTTP/1.1\r\n"
11257 "Host: www.example.com\r\n"
11258 "Proxy-Connection: keep-alive\r\n"
11259 "Authorization: auth_token\r\n\r\n");
11260 const MockWrite kGetAuthWithProxyAuth(
11261 "GET http://www.example.com/ HTTP/1.1\r\n"
11262 "Host: www.example.com\r\n"
11263 "Proxy-Connection: keep-alive\r\n"
11264 "Proxy-Authorization: auth_token\r\n"
11265 "Authorization: auth_token\r\n\r\n");
11266 const MockWrite kConnect(
11267 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711268 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1511269 "Proxy-Connection: keep-alive\r\n\r\n");
11270 const MockWrite kConnectProxyAuth(
11271 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711272 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1511273 "Proxy-Connection: keep-alive\r\n"
11274 "Proxy-Authorization: auth_token\r\n\r\n");
11275
11276 const MockRead kSuccess(
11277 "HTTP/1.1 200 OK\r\n"
11278 "Content-Type: text/html; charset=iso-8859-1\r\n"
11279 "Content-Length: 3\r\n\r\n"
11280 "Yes");
11281 const MockRead kFailure(
11282 "Should not be called.");
11283 const MockRead kServerChallenge(
11284 "HTTP/1.1 401 Unauthorized\r\n"
11285 "WWW-Authenticate: Mock realm=server\r\n"
11286 "Content-Type: text/html; charset=iso-8859-1\r\n"
11287 "Content-Length: 14\r\n\r\n"
11288 "Unauthorized\r\n");
11289 const MockRead kProxyChallenge(
11290 "HTTP/1.1 407 Unauthorized\r\n"
11291 "Proxy-Authenticate: Mock realm=proxy\r\n"
11292 "Proxy-Connection: close\r\n"
11293 "Content-Type: text/html; charset=iso-8859-1\r\n"
11294 "Content-Length: 14\r\n\r\n"
11295 "Unauthorized\r\n");
11296 const MockRead kProxyConnected(
11297 "HTTP/1.1 200 Connection Established\r\n\r\n");
11298
11299 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
11300 // no constructors, but the C++ compiler on Windows warns about
11301 // unspecified data in compound literals. So, moved to using constructors,
11302 // and TestRound's created with the default constructor should not be used.
11303 struct TestRound {
11304 TestRound()
11305 : expected_rv(ERR_UNEXPECTED),
11306 extra_write(NULL),
11307 extra_read(NULL) {
11308 }
11309 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
11310 int expected_rv_arg)
11311 : write(write_arg),
11312 read(read_arg),
11313 expected_rv(expected_rv_arg),
11314 extra_write(NULL),
11315 extra_read(NULL) {
11316 }
11317 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
11318 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0111319 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1511320 : write(write_arg),
11321 read(read_arg),
11322 expected_rv(expected_rv_arg),
11323 extra_write(extra_write_arg),
11324 extra_read(extra_read_arg) {
11325 }
11326 MockWrite write;
11327 MockRead read;
11328 int expected_rv;
11329 const MockWrite* extra_write;
11330 const MockRead* extra_read;
11331 };
11332
11333 static const int kNoSSL = 500;
11334
11335 struct TestConfig {
thestig9d3bb0c2015-01-24 00:49:5111336 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1511337 AuthTiming proxy_auth_timing;
11338 int proxy_auth_rv;
thestig9d3bb0c2015-01-24 00:49:5111339 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1511340 AuthTiming server_auth_timing;
11341 int server_auth_rv;
11342 int num_auth_rounds;
11343 int first_ssl_round;
11344 TestRound rounds[3];
11345 } test_configs[] = {
11346 // Non-authenticating HTTP server with a direct connection.
11347 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
11348 { TestRound(kGet, kSuccess, OK)}},
11349 // Authenticating HTTP server with a direct connection.
11350 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
11351 { TestRound(kGet, kServerChallenge, OK),
11352 TestRound(kGetAuth, kSuccess, OK)}},
11353 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
11354 { TestRound(kGet, kServerChallenge, OK),
11355 TestRound(kGetAuth, kFailure, kAuthErr)}},
11356 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
11357 { TestRound(kGet, kServerChallenge, OK),
11358 TestRound(kGetAuth, kSuccess, OK)}},
11359 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
11360 { TestRound(kGet, kServerChallenge, OK),
11361 TestRound(kGetAuth, kFailure, kAuthErr)}},
11362 // Non-authenticating HTTP server through a non-authenticating proxy.
11363 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
11364 { TestRound(kGetProxy, kSuccess, OK)}},
11365 // Authenticating HTTP server through a non-authenticating proxy.
11366 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
11367 { TestRound(kGetProxy, kServerChallenge, OK),
11368 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
11369 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
11370 { TestRound(kGetProxy, kServerChallenge, OK),
11371 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
11372 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
11373 { TestRound(kGetProxy, kServerChallenge, OK),
11374 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
11375 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
11376 { TestRound(kGetProxy, kServerChallenge, OK),
11377 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
11378 // Non-authenticating HTTP server through an authenticating proxy.
11379 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
11380 { TestRound(kGetProxy, kProxyChallenge, OK),
11381 TestRound(kGetProxyAuth, kSuccess, OK)}},
11382 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
11383 { TestRound(kGetProxy, kProxyChallenge, OK),
11384 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
11385 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
11386 { TestRound(kGetProxy, kProxyChallenge, OK),
11387 TestRound(kGetProxyAuth, kSuccess, OK)}},
11388 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
11389 { TestRound(kGetProxy, kProxyChallenge, OK),
11390 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
11391 // Authenticating HTTP server through an authenticating proxy.
11392 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
11393 { TestRound(kGetProxy, kProxyChallenge, OK),
11394 TestRound(kGetProxyAuth, kServerChallenge, OK),
11395 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11396 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
11397 { TestRound(kGetProxy, kProxyChallenge, OK),
11398 TestRound(kGetProxyAuth, kServerChallenge, OK),
11399 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11400 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
11401 { TestRound(kGetProxy, kProxyChallenge, OK),
11402 TestRound(kGetProxyAuth, kServerChallenge, OK),
11403 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11404 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
11405 { TestRound(kGetProxy, kProxyChallenge, OK),
11406 TestRound(kGetProxyAuth, kServerChallenge, OK),
11407 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11408 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
11409 { TestRound(kGetProxy, kProxyChallenge, OK),
11410 TestRound(kGetProxyAuth, kServerChallenge, OK),
11411 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11412 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
11413 { TestRound(kGetProxy, kProxyChallenge, OK),
11414 TestRound(kGetProxyAuth, kServerChallenge, OK),
11415 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11416 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
11417 { TestRound(kGetProxy, kProxyChallenge, OK),
11418 TestRound(kGetProxyAuth, kServerChallenge, OK),
11419 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11420 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
11421 { TestRound(kGetProxy, kProxyChallenge, OK),
11422 TestRound(kGetProxyAuth, kServerChallenge, OK),
11423 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11424 // Non-authenticating HTTPS server with a direct connection.
11425 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
11426 { TestRound(kGet, kSuccess, OK)}},
11427 // Authenticating HTTPS server with a direct connection.
11428 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
11429 { TestRound(kGet, kServerChallenge, OK),
11430 TestRound(kGetAuth, kSuccess, OK)}},
11431 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
11432 { TestRound(kGet, kServerChallenge, OK),
11433 TestRound(kGetAuth, kFailure, kAuthErr)}},
11434 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
11435 { TestRound(kGet, kServerChallenge, OK),
11436 TestRound(kGetAuth, kSuccess, OK)}},
11437 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
11438 { TestRound(kGet, kServerChallenge, OK),
11439 TestRound(kGetAuth, kFailure, kAuthErr)}},
11440 // Non-authenticating HTTPS server with a non-authenticating proxy.
11441 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
11442 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
11443 // Authenticating HTTPS server through a non-authenticating proxy.
11444 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
11445 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11446 TestRound(kGetAuth, kSuccess, OK)}},
11447 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
11448 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11449 TestRound(kGetAuth, kFailure, kAuthErr)}},
11450 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
11451 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11452 TestRound(kGetAuth, kSuccess, OK)}},
11453 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
11454 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11455 TestRound(kGetAuth, kFailure, kAuthErr)}},
11456 // Non-Authenticating HTTPS server through an authenticating proxy.
11457 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
11458 { TestRound(kConnect, kProxyChallenge, OK),
11459 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
11460 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
11461 { TestRound(kConnect, kProxyChallenge, OK),
11462 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
11463 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
11464 { TestRound(kConnect, kProxyChallenge, OK),
11465 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
11466 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
11467 { TestRound(kConnect, kProxyChallenge, OK),
11468 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
11469 // Authenticating HTTPS server through an authenticating proxy.
11470 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11471 { TestRound(kConnect, kProxyChallenge, OK),
11472 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11473 &kGet, &kServerChallenge),
11474 TestRound(kGetAuth, kSuccess, OK)}},
11475 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11476 { TestRound(kConnect, kProxyChallenge, OK),
11477 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11478 &kGet, &kServerChallenge),
11479 TestRound(kGetAuth, kFailure, kAuthErr)}},
11480 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11481 { TestRound(kConnect, kProxyChallenge, OK),
11482 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11483 &kGet, &kServerChallenge),
11484 TestRound(kGetAuth, kSuccess, OK)}},
11485 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11486 { TestRound(kConnect, kProxyChallenge, OK),
11487 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11488 &kGet, &kServerChallenge),
11489 TestRound(kGetAuth, kFailure, kAuthErr)}},
11490 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11491 { TestRound(kConnect, kProxyChallenge, OK),
11492 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11493 &kGet, &kServerChallenge),
11494 TestRound(kGetAuth, kSuccess, OK)}},
11495 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11496 { TestRound(kConnect, kProxyChallenge, OK),
11497 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11498 &kGet, &kServerChallenge),
11499 TestRound(kGetAuth, kFailure, kAuthErr)}},
11500 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11501 { TestRound(kConnect, kProxyChallenge, OK),
11502 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11503 &kGet, &kServerChallenge),
11504 TestRound(kGetAuth, kSuccess, OK)}},
11505 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11506 { TestRound(kConnect, kProxyChallenge, OK),
11507 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11508 &kGet, &kServerChallenge),
11509 TestRound(kGetAuth, kFailure, kAuthErr)}},
11510 };
11511
viettrungluue4a8b882014-10-16 06:17:3811512 for (size_t i = 0; i < arraysize(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:0811513 HttpAuthHandlerMock::Factory* auth_factory(
11514 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711515 session_deps_.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:1511516 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:2611517
11518 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1511519 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:0811520 for (int n = 0; n < 2; n++) {
11521 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11522 std::string auth_challenge = "Mock realm=proxy";
11523 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2411524 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11525 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0811526 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
11527 origin, BoundNetLog());
11528 auth_handler->SetGenerateExpectation(
11529 test_config.proxy_auth_timing == AUTH_ASYNC,
11530 test_config.proxy_auth_rv);
11531 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
11532 }
[email protected]044de0642010-06-17 10:42:1511533 }
11534 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0011535 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1511536 std::string auth_challenge = "Mock realm=server";
11537 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2411538 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11539 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1511540 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
11541 origin, BoundNetLog());
11542 auth_handler->SetGenerateExpectation(
11543 test_config.server_auth_timing == AUTH_ASYNC,
11544 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:0811545 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1511546 }
11547 if (test_config.proxy_url) {
rdsmith82957ad2015-09-16 19:42:0311548 session_deps_.proxy_service =
11549 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:1511550 } else {
rdsmith82957ad2015-09-16 19:42:0311551 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1511552 }
11553
11554 HttpRequestInfo request;
11555 request.method = "GET";
11556 request.url = GURL(test_config.server_url);
11557 request.load_flags = 0;
11558
mmenkee65e7af2015-10-13 17:16:4211559 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1511560
rchcb68dc62015-05-21 04:45:3611561 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
11562
11563 std::vector<std::vector<MockRead>> mock_reads(1);
11564 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1511565 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11566 const TestRound& read_write_round = test_config.rounds[round];
11567
11568 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3611569 mock_reads.back().push_back(read_write_round.read);
11570 mock_writes.back().push_back(read_write_round.write);
11571
11572 // kProxyChallenge uses Proxy-Connection: close which means that the
11573 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5411574 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3611575 mock_reads.push_back(std::vector<MockRead>());
11576 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1511577 }
11578
rchcb68dc62015-05-21 04:45:3611579 if (read_write_round.extra_read) {
11580 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1511581 }
rchcb68dc62015-05-21 04:45:3611582 if (read_write_round.extra_write) {
11583 mock_writes.back().push_back(*read_write_round.extra_write);
11584 }
[email protected]044de0642010-06-17 10:42:1511585
11586 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1511587 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0711588 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1511589 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3611590 }
[email protected]044de0642010-06-17 10:42:1511591
olli.raula525048c2015-12-10 07:38:3211592 std::vector<scoped_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3611593 for (size_t i = 0; i < mock_reads.size(); ++i) {
olli.raula525048c2015-12-10 07:38:3211594 data_providers.push_back(make_scoped_ptr(new StaticSocketDataProvider(
davidben5f8b6bc2015-11-25 03:19:5411595 mock_reads[i].data(), mock_reads[i].size(), mock_writes[i].data(),
olli.raula525048c2015-12-10 07:38:3211596 mock_writes[i].size())));
rchcb68dc62015-05-21 04:45:3611597 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3211598 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3611599 }
11600
mmenkecc2298e2015-12-07 18:20:1811601 // Transaction must be created after DataProviders, so it's destroyed before
11602 // they are as well.
11603 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11604
rchcb68dc62015-05-21 04:45:3611605 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11606 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1511607 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4111608 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1511609 int rv;
11610 if (round == 0) {
[email protected]49639fa2011-12-20 23:22:4111611 rv = trans.Start(&request, callback.callback(), BoundNetLog());
[email protected]044de0642010-06-17 10:42:1511612 } else {
[email protected]49639fa2011-12-20 23:22:4111613 rv = trans.RestartWithAuth(
11614 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1511615 }
11616 if (rv == ERR_IO_PENDING)
11617 rv = callback.WaitForResult();
11618
11619 // Compare results with expected data.
11620 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:5011621 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5511622 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1511623 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
11624 continue;
11625 }
11626 if (round + 1 < test_config.num_auth_rounds) {
11627 EXPECT_FALSE(response->auth_challenge.get() == NULL);
11628 } else {
11629 EXPECT_TRUE(response->auth_challenge.get() == NULL);
11630 }
11631 }
[email protected]e5ae96a2010-04-14 20:12:4511632 }
11633}
11634
[email protected]23e482282013-06-14 16:08:0211635TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1411636 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1411637 HttpAuthHandlerMock::Factory* auth_factory(
11638 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711639 session_deps_.http_auth_handler_factory.reset(auth_factory);
rdsmith82957ad2015-09-16 19:42:0311640 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0711641 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
11642 session_deps_.host_resolver->set_synchronous_mode(true);
[email protected]c871bce92010-07-15 21:51:1411643
11644 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11645 auth_handler->set_connection_based(true);
11646 std::string auth_challenge = "Mock realm=server";
11647 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2411648 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11649 auth_challenge.end());
[email protected]c871bce92010-07-15 21:51:1411650 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
11651 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:0811652 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1411653
[email protected]c871bce92010-07-15 21:51:1411654 int rv = OK;
11655 const HttpResponseInfo* response = NULL;
11656 HttpRequestInfo request;
11657 request.method = "GET";
11658 request.url = origin;
11659 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:2711660
mmenkee65e7af2015-10-13 17:16:4211661 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1011662
11663 // Use a TCP Socket Pool with only one connection per group. This is used
11664 // to validate that the TCP socket is not released to the pool between
11665 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4211666 HttpNetworkSessionPeer session_peer(session.get());
[email protected]ab739042011-04-07 15:22:2811667 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:1011668 50, // Max sockets for pool
11669 1, // Max sockets per group
[email protected]bb88e1d32013-05-03 23:11:0711670 session_deps_.host_resolver.get(),
11671 session_deps_.socket_factory.get(),
11672 session_deps_.net_log);
[email protected]831e4a32013-11-14 02:14:4411673 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
11674 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:0211675 mock_pool_manager->SetTransportSocketPool(transport_pool);
dchengc7eeda422015-12-26 03:56:4811676 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1011677
[email protected]262eec82013-03-19 21:01:3611678 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011679 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111680 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1411681
11682 const MockWrite kGet(
11683 "GET / HTTP/1.1\r\n"
11684 "Host: www.example.com\r\n"
11685 "Connection: keep-alive\r\n\r\n");
11686 const MockWrite kGetAuth(
11687 "GET / HTTP/1.1\r\n"
11688 "Host: www.example.com\r\n"
11689 "Connection: keep-alive\r\n"
11690 "Authorization: auth_token\r\n\r\n");
11691
11692 const MockRead kServerChallenge(
11693 "HTTP/1.1 401 Unauthorized\r\n"
11694 "WWW-Authenticate: Mock realm=server\r\n"
11695 "Content-Type: text/html; charset=iso-8859-1\r\n"
11696 "Content-Length: 14\r\n\r\n"
11697 "Unauthorized\r\n");
11698 const MockRead kSuccess(
11699 "HTTP/1.1 200 OK\r\n"
11700 "Content-Type: text/html; charset=iso-8859-1\r\n"
11701 "Content-Length: 3\r\n\r\n"
11702 "Yes");
11703
11704 MockWrite writes[] = {
11705 // First round
11706 kGet,
11707 // Second round
11708 kGetAuth,
11709 // Third round
11710 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3011711 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1011712 kGetAuth,
11713 // Competing request
11714 kGet,
[email protected]c871bce92010-07-15 21:51:1411715 };
11716 MockRead reads[] = {
11717 // First round
11718 kServerChallenge,
11719 // Second round
11720 kServerChallenge,
11721 // Third round
[email protected]eca50e122010-09-11 14:03:3011722 kServerChallenge,
11723 // Fourth round
[email protected]c871bce92010-07-15 21:51:1411724 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1011725 // Competing response
11726 kSuccess,
[email protected]c871bce92010-07-15 21:51:1411727 };
11728 StaticSocketDataProvider data_provider(reads, arraysize(reads),
11729 writes, arraysize(writes));
[email protected]bb88e1d32013-05-03 23:11:0711730 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1411731
thestig9d3bb0c2015-01-24 00:49:5111732 const char kSocketGroup[] = "www.example.com:80";
[email protected]7ef4cbbb2011-02-06 11:19:1011733
11734 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1411735 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111736 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]c871bce92010-07-15 21:51:1411737 if (rv == ERR_IO_PENDING)
11738 rv = callback.WaitForResult();
11739 EXPECT_EQ(OK, rv);
11740 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011741 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411742 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811743 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411744
[email protected]7ef4cbbb2011-02-06 11:19:1011745 // In between rounds, another request comes in for the same domain.
11746 // It should not be able to grab the TCP socket that trans has already
11747 // claimed.
11748 scoped_ptr<HttpTransaction> trans_compete(
[email protected]90499482013-06-01 00:39:5011749 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111750 TestCompletionCallback callback_compete;
11751 rv = trans_compete->Start(
11752 &request, callback_compete.callback(), BoundNetLog());
[email protected]7ef4cbbb2011-02-06 11:19:1011753 EXPECT_EQ(ERR_IO_PENDING, rv);
11754 // callback_compete.WaitForResult at this point would stall forever,
11755 // since the HttpNetworkTransaction does not release the request back to
11756 // the pool until after authentication completes.
11757
11758 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1411759 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111760 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411761 if (rv == ERR_IO_PENDING)
11762 rv = callback.WaitForResult();
11763 EXPECT_EQ(OK, rv);
11764 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011765 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411766 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811767 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411768
[email protected]7ef4cbbb2011-02-06 11:19:1011769 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1411770 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111771 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411772 if (rv == ERR_IO_PENDING)
11773 rv = callback.WaitForResult();
11774 EXPECT_EQ(OK, rv);
11775 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011776 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:1411777 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811778 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:3011779
[email protected]7ef4cbbb2011-02-06 11:19:1011780 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3011781 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111782 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3011783 if (rv == ERR_IO_PENDING)
11784 rv = callback.WaitForResult();
11785 EXPECT_EQ(OK, rv);
11786 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5011787 ASSERT_TRUE(response != NULL);
[email protected]eca50e122010-09-11 14:03:3011788 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:2811789 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011790
11791 // Read the body since the fourth round was successful. This will also
11792 // release the socket back to the pool.
11793 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
[email protected]90499482013-06-01 00:39:5011794 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011795 if (rv == ERR_IO_PENDING)
11796 rv = callback.WaitForResult();
11797 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011798 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011799 EXPECT_EQ(0, rv);
11800 // There are still 0 idle sockets, since the trans_compete transaction
11801 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:2811802 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011803
11804 // The competing request can now finish. Wait for the headers and then
11805 // read the body.
11806 rv = callback_compete.WaitForResult();
11807 EXPECT_EQ(OK, rv);
[email protected]90499482013-06-01 00:39:5011808 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011809 if (rv == ERR_IO_PENDING)
11810 rv = callback.WaitForResult();
11811 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011812 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011813 EXPECT_EQ(0, rv);
11814
11815 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:2811816 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411817}
11818
[email protected]65041fa2010-05-21 06:56:5311819// This tests the case that a request is issued via http instead of spdy after
11820// npn is negotiated.
[email protected]23e482282013-06-14 16:08:0211821TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
bncf33fb31b2016-01-29 15:22:2611822 session_deps_.parse_alternative_services = true;
11823 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]d7599122014-05-24 03:37:2311824
[email protected]65041fa2010-05-21 06:56:5311825 HttpRequestInfo request;
11826 request.method = "GET";
bncce36dca22015-04-21 22:11:2311827 request.url = GURL("https://www.example.org/");
[email protected]65041fa2010-05-21 06:56:5311828 request.load_flags = 0;
11829
11830 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311831 MockWrite(
11832 "GET / HTTP/1.1\r\n"
11833 "Host: www.example.org\r\n"
11834 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5311835 };
11836
[email protected]8a0fc822013-06-27 20:52:4311837 std::string alternate_protocol_http_header =
11838 GetAlternateProtocolHttpHeader();
11839
[email protected]65041fa2010-05-21 06:56:5311840 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211841 MockRead("HTTP/1.1 200 OK\r\n"),
11842 MockRead(alternate_protocol_http_header.c_str()),
11843 MockRead("\r\n"),
11844 MockRead("hello world"),
11845 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5311846 };
11847
[email protected]8ddf8322012-02-23 18:08:0611848 SSLSocketDataProvider ssl(ASYNC, OK);
davidben6974bf72015-04-27 17:52:4811849 ssl.SetNextProto(kProtoHTTP11);
[email protected]65041fa2010-05-21 06:56:5311850
[email protected]bb88e1d32013-05-03 23:11:0711851 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5311852
11853 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11854 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0711855 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5311856
[email protected]49639fa2011-12-20 23:22:4111857 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5311858
mmenkee65e7af2015-10-13 17:16:4211859 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3611860 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011861 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]65041fa2010-05-21 06:56:5311862
[email protected]49639fa2011-12-20 23:22:4111863 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]65041fa2010-05-21 06:56:5311864
11865 EXPECT_EQ(ERR_IO_PENDING, rv);
11866 EXPECT_EQ(OK, callback.WaitForResult());
11867
11868 const HttpResponseInfo* response = trans->GetResponseInfo();
11869 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5011870 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]65041fa2010-05-21 06:56:5311871 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11872
11873 std::string response_data;
11874 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11875 EXPECT_EQ("hello world", response_data);
11876
11877 EXPECT_FALSE(response->was_fetched_via_spdy);
11878 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]65041fa2010-05-21 06:56:5311879}
[email protected]26ef6582010-06-24 02:30:4711880
bnc55ff9da2015-08-19 18:42:3511881// Simulate the SSL handshake completing with an NPN negotiation followed by an
11882// immediate server closing of the socket.
11883// Regression test for https://crbug.com/46369.
[email protected]23e482282013-06-14 16:08:0211884TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
bncf33fb31b2016-01-29 15:22:2611885 session_deps_.parse_alternative_services = true;
11886 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]26ef6582010-06-24 02:30:4711887
11888 HttpRequestInfo request;
11889 request.method = "GET";
bncce36dca22015-04-21 22:11:2311890 request.url = GURL("https://www.example.org/");
[email protected]26ef6582010-06-24 02:30:4711891 request.load_flags = 0;
11892
[email protected]8ddf8322012-02-23 18:08:0611893 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3811894 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0711895 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4711896
[email protected]cdf8f7e72013-05-23 10:56:4611897 scoped_ptr<SpdyFrame> req(
bnc38dcd392016-02-09 23:19:4911898 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
rch8e6c6c42015-05-01 14:05:1311899 MockWrite spdy_writes[] = {CreateMockWrite(*req, 1)};
[email protected]26ef6582010-06-24 02:30:4711900
11901 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0611902 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4711903 };
11904
rch8e6c6c42015-05-01 14:05:1311905 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11906 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711907 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4711908
[email protected]49639fa2011-12-20 23:22:4111909 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4711910
mmenkee65e7af2015-10-13 17:16:4211911 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3611912 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011913 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]26ef6582010-06-24 02:30:4711914
[email protected]49639fa2011-12-20 23:22:4111915 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]26ef6582010-06-24 02:30:4711916 EXPECT_EQ(ERR_IO_PENDING, rv);
11917 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
[email protected]26ef6582010-06-24 02:30:4711918}
[email protected]65d34382010-07-01 18:12:2611919
[email protected]795cbf82013-07-22 09:37:2711920// A subclass of HttpAuthHandlerMock that records the request URL when
11921// it gets it. This is needed since the auth handler may get destroyed
11922// before we get a chance to query it.
11923class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
11924 public:
11925 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
11926
dchengb03027d2014-10-21 12:00:2011927 ~UrlRecordingHttpAuthHandlerMock() override {}
[email protected]795cbf82013-07-22 09:37:2711928
11929 protected:
dchengb03027d2014-10-21 12:00:2011930 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
11931 const HttpRequestInfo* request,
11932 const CompletionCallback& callback,
11933 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2711934 *url_ = request->url;
11935 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
11936 credentials, request, callback, auth_token);
11937 }
11938
11939 private:
11940 GURL* url_;
11941};
11942
bnc55ff9da2015-08-19 18:42:3511943// This test ensures that the URL passed into the proxy is upgraded to https
11944// when doing an Alternate Protocol upgrade.
[email protected]23e482282013-06-14 16:08:0211945TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
rch3f4b8452016-02-23 16:59:3211946 session_deps_.parse_alternative_services = false;
bncf33fb31b2016-01-29 15:22:2611947 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]f45c1ee2010-08-03 00:54:3011948
rdsmith82957ad2015-09-16 19:42:0311949 session_deps_.proxy_service =
11950 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5111951 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711952 session_deps_.net_log = &net_log;
[email protected]795cbf82013-07-22 09:37:2711953 GURL request_url;
11954 {
11955 HttpAuthHandlerMock::Factory* auth_factory =
11956 new HttpAuthHandlerMock::Factory();
11957 UrlRecordingHttpAuthHandlerMock* auth_handler =
11958 new UrlRecordingHttpAuthHandlerMock(&request_url);
11959 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
11960 auth_factory->set_do_init_from_challenge(true);
11961 session_deps_.http_auth_handler_factory.reset(auth_factory);
11962 }
[email protected]f45c1ee2010-08-03 00:54:3011963
11964 HttpRequestInfo request;
11965 request.method = "GET";
bncce36dca22015-04-21 22:11:2311966 request.url = GURL("http://www.example.org");
[email protected]f45c1ee2010-08-03 00:54:3011967 request.load_flags = 0;
11968
11969 // First round goes unauthenticated through the proxy.
11970 MockWrite data_writes_1[] = {
bncce36dca22015-04-21 22:11:2311971 MockWrite(
11972 "GET http://www.example.org/ HTTP/1.1\r\n"
11973 "Host: www.example.org\r\n"
11974 "Proxy-Connection: keep-alive\r\n"
11975 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011976 };
11977 MockRead data_reads_1[] = {
[email protected]8ddf8322012-02-23 18:08:0611978 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
bnc33b8cef42014-11-19 17:30:3811979 MockRead("HTTP/1.1 200 OK\r\n"),
11980 MockRead("Alternate-Protocol: 443:"),
11981 MockRead(GetAlternateProtocolFromParam()),
11982 MockRead("\r\n"),
11983 MockRead("Proxy-Connection: close\r\n"),
11984 MockRead("\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3011985 };
11986 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
11987 data_writes_1, arraysize(data_writes_1));
11988
bncce36dca22015-04-21 22:11:2311989 // Second round tries to tunnel to www.example.org due to the
[email protected]f45c1ee2010-08-03 00:54:3011990 // Alternate-Protocol announcement in the first round. It fails due
11991 // to a proxy authentication challenge.
bncce36dca22015-04-21 22:11:2311992 // After the failure, a tunnel is established to www.example.org using
[email protected]394816e92010-08-03 07:38:5911993 // Proxy-Authorization headers. There is then a SPDY request round.
11994 //
[email protected]fe3b7dc2012-02-03 19:52:0911995 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
11996 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
11997 // does a Disconnect and Connect on the same socket, rather than trying
11998 // to obtain a new one.
11999 //
[email protected]394816e92010-08-03 07:38:5912000 // NOTE: Originally, the proxy response to the second CONNECT request
12001 // simply returned another 407 so the unit test could skip the SSL connection
12002 // establishment and SPDY framing issues. Alas, the
12003 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:3012004 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:5912005
[email protected]cdf8f7e72013-05-23 10:56:4612006 scoped_ptr<SpdyFrame> req(
bnc38dcd392016-02-09 23:19:4912007 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
[email protected]23e482282013-06-14 16:08:0212008 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12009 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]f45c1ee2010-08-03 00:54:3012010
[email protected]394816e92010-08-03 07:38:5912011 MockWrite data_writes_2[] = {
bncce36dca22015-04-21 22:11:2312012 // First connection attempt without Proxy-Authorization.
rch8e6c6c42015-05-01 14:05:1312013 MockWrite(ASYNC, 0,
12014 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1712015 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1312016 "Proxy-Connection: keep-alive\r\n"
12017 "\r\n"),
[email protected]394816e92010-08-03 07:38:5912018
bncce36dca22015-04-21 22:11:2312019 // Second connection attempt with Proxy-Authorization.
rch8e6c6c42015-05-01 14:05:1312020 MockWrite(ASYNC, 2,
12021 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1712022 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1312023 "Proxy-Connection: keep-alive\r\n"
12024 "Proxy-Authorization: auth_token\r\n"
12025 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:3012026
bncce36dca22015-04-21 22:11:2312027 // SPDY request
rch8e6c6c42015-05-01 14:05:1312028 CreateMockWrite(*req, 4),
[email protected]f45c1ee2010-08-03 00:54:3012029 };
[email protected]394816e92010-08-03 07:38:5912030 MockRead data_reads_2[] = {
rch8e6c6c42015-05-01 14:05:1312031 // First connection attempt fails
mmenkee71e15332015-10-07 16:39:5412032 MockRead(ASYNC, 1,
12033 "HTTP/1.1 407 Unauthorized\r\n"
12034 "Proxy-Authenticate: Mock\r\n"
12035 "Content-Length: 0\r\n"
12036 "Proxy-Connection: keep-alive\r\n"
12037 "\r\n"),
[email protected]394816e92010-08-03 07:38:5912038
rch8e6c6c42015-05-01 14:05:1312039 // Second connection attempt passes
mmenkee71e15332015-10-07 16:39:5412040 MockRead(ASYNC, 3, "HTTP/1.1 200 Connected\r\n\r\n"),
[email protected]394816e92010-08-03 07:38:5912041
rch8e6c6c42015-05-01 14:05:1312042 // SPDY response
mmenkee71e15332015-10-07 16:39:5412043 CreateMockRead(*resp.get(), 5), CreateMockRead(*data.get(), 6),
rch8e6c6c42015-05-01 14:05:1312044 MockRead(ASYNC, 0, 0, 7),
[email protected]394816e92010-08-03 07:38:5912045 };
rch8e6c6c42015-05-01 14:05:1312046 SequencedSocketData data_2(data_reads_2, arraysize(data_reads_2),
12047 data_writes_2, arraysize(data_writes_2));
[email protected]f45c1ee2010-08-03 00:54:3012048
[email protected]8ddf8322012-02-23 18:08:0612049 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812050 ssl.SetNextProto(GetProtocol());
bncce36dca22015-04-21 22:11:2312051 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
12052 ASSERT_TRUE(ssl.cert.get());
[email protected]f45c1ee2010-08-03 00:54:3012053
[email protected]d973e99a2012-02-17 21:02:3612054 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5512055 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
12056 NULL, 0, NULL, 0);
12057 hanging_non_alternate_protocol_socket.set_connect_data(
12058 never_finishing_connect);
12059
[email protected]bb88e1d32013-05-03 23:11:0712060 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
12061 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
12062 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12063 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5512064 &hanging_non_alternate_protocol_socket);
mmenkee65e7af2015-10-13 17:16:4212065 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f45c1ee2010-08-03 00:54:3012066
12067 // First round should work and provide the Alternate-Protocol state.
[email protected]49639fa2011-12-20 23:22:4112068 TestCompletionCallback callback_1;
[email protected]262eec82013-03-19 21:01:3612069 scoped_ptr<HttpTransaction> trans_1(
[email protected]90499482013-06-01 00:39:5012070 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4112071 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:3012072 EXPECT_EQ(ERR_IO_PENDING, rv);
12073 EXPECT_EQ(OK, callback_1.WaitForResult());
12074
12075 // Second round should attempt a tunnel connect and get an auth challenge.
[email protected]49639fa2011-12-20 23:22:4112076 TestCompletionCallback callback_2;
[email protected]262eec82013-03-19 21:01:3612077 scoped_ptr<HttpTransaction> trans_2(
[email protected]90499482013-06-01 00:39:5012078 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4112079 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:3012080 EXPECT_EQ(ERR_IO_PENDING, rv);
12081 EXPECT_EQ(OK, callback_2.WaitForResult());
12082 const HttpResponseInfo* response = trans_2->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5012083 ASSERT_TRUE(response != NULL);
[email protected]f45c1ee2010-08-03 00:54:3012084 ASSERT_FALSE(response->auth_challenge.get() == NULL);
12085
12086 // Restart with auth. Tunnel should work and response received.
[email protected]49639fa2011-12-20 23:22:4112087 TestCompletionCallback callback_3;
12088 rv = trans_2->RestartWithAuth(
12089 AuthCredentials(kFoo, kBar), callback_3.callback());
[email protected]f45c1ee2010-08-03 00:54:3012090 EXPECT_EQ(ERR_IO_PENDING, rv);
12091 EXPECT_EQ(OK, callback_3.WaitForResult());
12092
12093 // After all that work, these two lines (or actually, just the scheme) are
12094 // what this test is all about. Make sure it happens correctly.
[email protected]f45c1ee2010-08-03 00:54:3012095 EXPECT_EQ("https", request_url.scheme());
bncce36dca22015-04-21 22:11:2312096 EXPECT_EQ("www.example.org", request_url.host());
[email protected]f45c1ee2010-08-03 00:54:3012097
[email protected]029c83b62013-01-24 05:28:2012098 LoadTimingInfo load_timing_info;
12099 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
12100 TestLoadTimingNotReusedWithPac(load_timing_info,
12101 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]8e6441ca2010-08-19 05:56:3812102}
12103
12104// Test that if we cancel the transaction as the connection is completing, that
12105// everything tears down correctly.
[email protected]23e482282013-06-14 16:08:0212106TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3812107 // Setup everything about the connection to complete synchronously, so that
12108 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
12109 // for is the callback from the HttpStreamRequest.
12110 // Then cancel the transaction.
12111 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3612112 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3812113 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0612114 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
12115 MockRead(SYNCHRONOUS, "hello world"),
12116 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3812117 };
12118
[email protected]8e6441ca2010-08-19 05:56:3812119 HttpRequestInfo request;
12120 request.method = "GET";
bncce36dca22015-04-21 22:11:2312121 request.url = GURL("http://www.example.org/");
[email protected]8e6441ca2010-08-19 05:56:3812122 request.load_flags = 0;
12123
[email protected]bb88e1d32013-05-03 23:11:0712124 session_deps_.host_resolver->set_synchronous_mode(true);
mmenkee65e7af2015-10-13 17:16:4212125 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:2712126 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4112127 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:2712128
[email protected]8e6441ca2010-08-19 05:56:3812129 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
12130 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712131 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3812132
[email protected]49639fa2011-12-20 23:22:4112133 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3812134
vishal.b62985ca92015-04-17 08:45:5112135 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4112136 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]8e6441ca2010-08-19 05:56:3812137 EXPECT_EQ(ERR_IO_PENDING, rv);
12138 trans.reset(); // Cancel the transaction here.
12139
[email protected]2da659e2013-05-23 20:51:3412140 base::MessageLoop::current()->RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3012141}
12142
[email protected]ecab6e052014-05-16 14:58:1212143// Test that if a transaction is cancelled after receiving the headers, the
12144// stream is drained properly and added back to the socket pool. The main
12145// purpose of this test is to make sure that an HttpStreamParser can be read
12146// from after the HttpNetworkTransaction and the objects it owns have been
12147// deleted.
12148// See http://crbug.com/368418
12149TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
12150 MockRead data_reads[] = {
12151 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
12152 MockRead(ASYNC, "Content-Length: 2\r\n"),
12153 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
12154 MockRead(ASYNC, "1"),
12155 // 2 async reads are necessary to trigger a ReadResponseBody call after the
12156 // HttpNetworkTransaction has been deleted.
12157 MockRead(ASYNC, "2"),
12158 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
12159 };
12160 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
12161 session_deps_.socket_factory->AddSocketDataProvider(&data);
12162
mmenkee65e7af2015-10-13 17:16:4212163 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1212164
12165 {
12166 HttpRequestInfo request;
12167 request.method = "GET";
bncce36dca22015-04-21 22:11:2312168 request.url = GURL("http://www.example.org/");
[email protected]ecab6e052014-05-16 14:58:1212169 request.load_flags = 0;
12170
dcheng48459ac22014-08-26 00:46:4112171 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1212172 TestCompletionCallback callback;
12173
12174 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
12175 EXPECT_EQ(ERR_IO_PENDING, rv);
12176 callback.WaitForResult();
12177
12178 const HttpResponseInfo* response = trans.GetResponseInfo();
12179 ASSERT_TRUE(response != NULL);
12180 EXPECT_TRUE(response->headers.get() != NULL);
12181 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12182
12183 // The transaction and HttpRequestInfo are deleted.
12184 }
12185
12186 // Let the HttpResponseBodyDrainer drain the socket.
12187 base::MessageLoop::current()->RunUntilIdle();
12188
12189 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4112190 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1212191}
12192
[email protected]76a505b2010-08-25 06:23:0012193// Test a basic GET request through a proxy.
[email protected]23e482282013-06-14 16:08:0212194TEST_P(HttpNetworkTransactionTest, ProxyGet) {
rdsmith82957ad2015-09-16 19:42:0312195 session_deps_.proxy_service =
12196 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112197 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712198 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4212199 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012200
[email protected]76a505b2010-08-25 06:23:0012201 HttpRequestInfo request;
12202 request.method = "GET";
bncce36dca22015-04-21 22:11:2312203 request.url = GURL("http://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012204
12205 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312206 MockWrite(
12207 "GET http://www.example.org/ HTTP/1.1\r\n"
12208 "Host: www.example.org\r\n"
12209 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012210 };
12211
12212 MockRead data_reads1[] = {
12213 MockRead("HTTP/1.1 200 OK\r\n"),
12214 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12215 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612216 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0012217 };
12218
12219 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12220 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712221 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0012222
[email protected]49639fa2011-12-20 23:22:4112223 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012224
[email protected]262eec82013-03-19 21:01:3612225 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012226 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]597a1ab2014-06-26 08:12:2712227 BeforeProxyHeadersSentHandler proxy_headers_handler;
12228 trans->SetBeforeProxyHeadersSentCallback(
12229 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
12230 base::Unretained(&proxy_headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5012231
[email protected]49639fa2011-12-20 23:22:4112232 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0012233 EXPECT_EQ(ERR_IO_PENDING, rv);
12234
12235 rv = callback1.WaitForResult();
12236 EXPECT_EQ(OK, rv);
12237
12238 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5012239 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:0012240
12241 EXPECT_TRUE(response->headers->IsKeepAlive());
12242 EXPECT_EQ(200, response->headers->response_code());
12243 EXPECT_EQ(100, response->headers->GetContentLength());
12244 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1512245 EXPECT_TRUE(
12246 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
[email protected]597a1ab2014-06-26 08:12:2712247 EXPECT_TRUE(proxy_headers_handler.observed_before_proxy_headers_sent());
12248 EXPECT_EQ("myproxy:70", proxy_headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0012249 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2012250
12251 LoadTimingInfo load_timing_info;
12252 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12253 TestLoadTimingNotReusedWithPac(load_timing_info,
12254 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0012255}
12256
12257// Test a basic HTTPS GET request through a proxy.
[email protected]23e482282013-06-14 16:08:0212258TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
rdsmith82957ad2015-09-16 19:42:0312259 session_deps_.proxy_service =
12260 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112261 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712262 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4212263 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012264
[email protected]76a505b2010-08-25 06:23:0012265 HttpRequestInfo request;
12266 request.method = "GET";
bncce36dca22015-04-21 22:11:2312267 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012268
12269 // Since we have proxy, should try to establish tunnel.
12270 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1712271 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
12272 "Host: www.example.org:443\r\n"
12273 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012274
rsleevidb16bb02015-11-12 23:47:1712275 MockWrite("GET / HTTP/1.1\r\n"
12276 "Host: www.example.org\r\n"
12277 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012278 };
12279
12280 MockRead data_reads1[] = {
12281 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
12282
12283 MockRead("HTTP/1.1 200 OK\r\n"),
12284 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12285 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612286 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0012287 };
12288
12289 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12290 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712291 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0612292 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712293 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0012294
[email protected]49639fa2011-12-20 23:22:4112295 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012296
[email protected]262eec82013-03-19 21:01:3612297 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012298 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:5012299
[email protected]49639fa2011-12-20 23:22:4112300 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0012301 EXPECT_EQ(ERR_IO_PENDING, rv);
12302
12303 rv = callback1.WaitForResult();
12304 EXPECT_EQ(OK, rv);
mmenke43758e62015-05-04 21:09:4612305 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4012306 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0012307 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012308 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0012309 NetLog::PHASE_NONE);
12310 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012311 entries, pos,
[email protected]76a505b2010-08-25 06:23:0012312 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12313 NetLog::PHASE_NONE);
12314
12315 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:5012316 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:0012317
12318 EXPECT_TRUE(response->headers->IsKeepAlive());
12319 EXPECT_EQ(200, response->headers->response_code());
12320 EXPECT_EQ(100, response->headers->GetContentLength());
12321 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
12322 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1512323 EXPECT_TRUE(
12324 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
[email protected]029c83b62013-01-24 05:28:2012325
12326 LoadTimingInfo load_timing_info;
12327 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12328 TestLoadTimingNotReusedWithPac(load_timing_info,
12329 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0012330}
12331
rsleevidb16bb02015-11-12 23:47:1712332// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
12333// literal host.
12334TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
12335 session_deps_.proxy_service =
12336 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
12337 BoundTestNetLog log;
12338 session_deps_.net_log = log.bound().net_log();
12339 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12340
12341 HttpRequestInfo request;
12342 request.method = "GET";
12343 request.url = GURL("https://[::1]:443/");
12344
12345 // Since we have proxy, should try to establish tunnel.
12346 MockWrite data_writes1[] = {
12347 MockWrite("CONNECT [::1]:443 HTTP/1.1\r\n"
12348 "Host: [::1]:443\r\n"
12349 "Proxy-Connection: keep-alive\r\n\r\n"),
12350
12351 MockWrite("GET / HTTP/1.1\r\n"
12352 "Host: [::1]\r\n"
12353 "Connection: keep-alive\r\n\r\n"),
12354 };
12355
12356 MockRead data_reads1[] = {
12357 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
12358
12359 MockRead("HTTP/1.1 200 OK\r\n"),
12360 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12361 MockRead("Content-Length: 100\r\n\r\n"),
12362 MockRead(SYNCHRONOUS, OK),
12363 };
12364
12365 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12366 data_writes1, arraysize(data_writes1));
12367 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12368 SSLSocketDataProvider ssl(ASYNC, OK);
12369 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12370
12371 TestCompletionCallback callback1;
12372
12373 scoped_ptr<HttpTransaction> trans(
12374 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12375
12376 int rv = trans->Start(&request, callback1.callback(), log.bound());
12377 EXPECT_EQ(ERR_IO_PENDING, rv);
12378
12379 rv = callback1.WaitForResult();
12380 EXPECT_EQ(OK, rv);
12381 TestNetLogEntry::List entries;
12382 log.GetEntries(&entries);
12383 size_t pos = ExpectLogContainsSomewhere(
12384 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
12385 NetLog::PHASE_NONE);
12386 ExpectLogContainsSomewhere(
12387 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12388 NetLog::PHASE_NONE);
12389
12390 const HttpResponseInfo* response = trans->GetResponseInfo();
12391 ASSERT_TRUE(response != NULL);
12392
12393 EXPECT_TRUE(response->headers->IsKeepAlive());
12394 EXPECT_EQ(200, response->headers->response_code());
12395 EXPECT_EQ(100, response->headers->GetContentLength());
12396 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
12397 EXPECT_TRUE(response->was_fetched_via_proxy);
12398 EXPECT_TRUE(
12399 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
12400
12401 LoadTimingInfo load_timing_info;
12402 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12403 TestLoadTimingNotReusedWithPac(load_timing_info,
12404 CONNECT_TIMING_HAS_SSL_TIMES);
12405}
12406
[email protected]76a505b2010-08-25 06:23:0012407// Test a basic HTTPS GET request through a proxy, but the server hangs up
12408// while establishing the tunnel.
[email protected]23e482282013-06-14 16:08:0212409TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
rdsmith82957ad2015-09-16 19:42:0312410 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112411 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712412 session_deps_.net_log = log.bound().net_log();
mmenkee65e7af2015-10-13 17:16:4212413 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012414
[email protected]76a505b2010-08-25 06:23:0012415 HttpRequestInfo request;
12416 request.method = "GET";
bncce36dca22015-04-21 22:11:2312417 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012418
12419 // Since we have proxy, should try to establish tunnel.
12420 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1712421 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
12422 "Host: www.example.org:443\r\n"
12423 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012424
rsleevidb16bb02015-11-12 23:47:1712425 MockWrite("GET / HTTP/1.1\r\n"
12426 "Host: www.example.org\r\n"
12427 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012428 };
12429
12430 MockRead data_reads1[] = {
[email protected]8ddf8322012-02-23 18:08:0612431 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]76a505b2010-08-25 06:23:0012432 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612433 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0012434 };
12435
12436 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12437 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712438 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0612439 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712440 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0012441
[email protected]49639fa2011-12-20 23:22:4112442 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012443
[email protected]262eec82013-03-19 21:01:3612444 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012445 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:5012446
[email protected]49639fa2011-12-20 23:22:4112447 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:0012448 EXPECT_EQ(ERR_IO_PENDING, rv);
12449
12450 rv = callback1.WaitForResult();
12451 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
mmenke43758e62015-05-04 21:09:4612452 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4012453 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0012454 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012455 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0012456 NetLog::PHASE_NONE);
12457 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012458 entries, pos,
[email protected]76a505b2010-08-25 06:23:0012459 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12460 NetLog::PHASE_NONE);
12461}
12462
[email protected]749eefa82010-09-13 22:14:0312463// Test for crbug.com/55424.
[email protected]23e482282013-06-14 16:08:0212464TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
[email protected]cdf8f7e72013-05-23 10:56:4612465 scoped_ptr<SpdyFrame> req(
bnc38dcd392016-02-09 23:19:4912466 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rch8e6c6c42015-05-01 14:05:1312467 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]749eefa82010-09-13 22:14:0312468
[email protected]23e482282013-06-14 16:08:0212469 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12470 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0312471 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312472 CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0312473 };
12474
rch8e6c6c42015-05-01 14:05:1312475 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
12476 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712477 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0312478
[email protected]8ddf8322012-02-23 18:08:0612479 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812480 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712481 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0312482
mmenkee65e7af2015-10-13 17:16:4212483 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0312484
12485 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2312486 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4012487 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5312488 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2712489 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:4212490 CreateInsecureSpdySession(session.get(), key, BoundNetLog());
[email protected]749eefa82010-09-13 22:14:0312491
12492 HttpRequestInfo request;
12493 request.method = "GET";
bncce36dca22015-04-21 22:11:2312494 request.url = GURL("https://www.example.org/");
[email protected]749eefa82010-09-13 22:14:0312495 request.load_flags = 0;
12496
12497 // This is the important line that marks this as a preconnect.
12498 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
12499
[email protected]262eec82013-03-19 21:01:3612500 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012501 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]749eefa82010-09-13 22:14:0312502
[email protected]41d64e82013-07-03 22:44:2612503 TestCompletionCallback callback;
[email protected]49639fa2011-12-20 23:22:4112504 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]749eefa82010-09-13 22:14:0312505 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112506 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]749eefa82010-09-13 22:14:0312507}
12508
[email protected]73b8dd222010-11-11 19:55:2412509// Given a net error, cause that error to be returned from the first Write()
12510// call and verify that the HttpTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0212511void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0712512 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2912513 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712514 request_info.url = GURL("https://www.example.com/");
12515 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912516 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712517
[email protected]8ddf8322012-02-23 18:08:0612518 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2912519 MockWrite data_writes[] = {
12520 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2412521 };
ttuttle859dc7a2015-04-23 19:42:2912522 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0712523 session_deps_.socket_factory->AddSocketDataProvider(&data);
12524 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2412525
mmenkee65e7af2015-10-13 17:16:4212526 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612527 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012528 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]73b8dd222010-11-11 19:55:2412529
[email protected]49639fa2011-12-20 23:22:4112530 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912531 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12532 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2412533 rv = callback.WaitForResult();
12534 ASSERT_EQ(error, rv);
12535}
12536
[email protected]23e482282013-06-14 16:08:0212537TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2412538 // Just check a grab bag of cert errors.
12539 static const int kErrors[] = {
12540 ERR_CERT_COMMON_NAME_INVALID,
12541 ERR_CERT_AUTHORITY_INVALID,
12542 ERR_CERT_DATE_INVALID,
12543 };
12544 for (size_t i = 0; i < arraysize(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0612545 CheckErrorIsPassedBack(kErrors[i], ASYNC);
12546 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2412547 }
12548}
12549
[email protected]bd0b6772011-01-11 19:59:3012550// Ensure that a client certificate is removed from the SSL client auth
12551// cache when:
12552// 1) No proxy is involved.
12553// 2) TLS False Start is disabled.
12554// 3) The initial TLS handshake requests a client certificate.
12555// 4) The client supplies an invalid/unacceptable certificate.
[email protected]23e482282013-06-14 16:08:0212556TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2312557 ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912558 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712559 request_info.url = GURL("https://www.example.com/");
12560 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912561 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712562
[email protected]bd0b6772011-01-11 19:59:3012563 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112564 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012565
12566 // [ssl_]data1 contains the data for the first SSL handshake. When a
12567 // CertificateRequest is received for the first time, the handshake will
12568 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2912569 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012570 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712571 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912572 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712573 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012574
12575 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
12576 // False Start is not being used, the result of the SSL handshake will be
12577 // returned as part of the SSLClientSocket::Connect() call. This test
12578 // matches the result of a server sending a handshake_failure alert,
12579 // rather than a Finished message, because it requires a client
12580 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2912581 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012582 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712583 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912584 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712585 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012586
12587 // [ssl_]data3 contains the data for the third SSL handshake. When a
12588 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212589 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
12590 // connection was attempted with TLSv1.2. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3012591 // of the HttpNetworkTransaction. Because this test failure is due to
12592 // requiring a client certificate, this fallback handshake should also
12593 // fail.
ttuttle859dc7a2015-04-23 19:42:2912594 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012595 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712596 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912597 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712598 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012599
[email protected]80c75f682012-05-26 16:22:1712600 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
12601 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212602 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
12603 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1712604 // of the HttpNetworkTransaction. Because this test failure is due to
12605 // requiring a client certificate, this fallback handshake should also
12606 // fail.
ttuttle859dc7a2015-04-23 19:42:2912607 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1712608 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712609 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912610 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712611 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712612
mmenkee65e7af2015-10-13 17:16:4212613 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612614 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012615 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012616
[email protected]bd0b6772011-01-11 19:59:3012617 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4112618 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912619 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12620 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012621
12622 // Complete the SSL handshake, which should abort due to requiring a
12623 // client certificate.
12624 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912625 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]bd0b6772011-01-11 19:59:3012626
12627 // Indicate that no certificate should be supplied. From the perspective
12628 // of SSLClientCertCache, NULL is just as meaningful as a real
12629 // certificate, so this is the same as supply a
12630 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412631 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912632 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012633
12634 // Ensure the certificate was added to the client auth cache before
12635 // allowing the connection to continue restarting.
12636 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412637 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112638 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412639 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012640 ASSERT_EQ(NULL, client_cert.get());
12641
12642 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712643 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12644 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012645 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912646 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
[email protected]bd0b6772011-01-11 19:59:3012647
12648 // Ensure that the client certificate is removed from the cache on a
12649 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112650 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412651 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012652}
12653
12654// Ensure that a client certificate is removed from the SSL client auth
12655// cache when:
12656// 1) No proxy is involved.
12657// 2) TLS False Start is enabled.
12658// 3) The initial TLS handshake requests a client certificate.
12659// 4) The client supplies an invalid/unacceptable certificate.
[email protected]23e482282013-06-14 16:08:0212660TEST_P(HttpNetworkTransactionTest,
[email protected]448d4ca52012-03-04 04:12:2312661 ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912662 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712663 request_info.url = GURL("https://www.example.com/");
12664 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912665 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712666
[email protected]bd0b6772011-01-11 19:59:3012667 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112668 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012669
12670 // When TLS False Start is used, SSLClientSocket::Connect() calls will
12671 // return successfully after reading up to the peer's Certificate message.
12672 // This is to allow the caller to call SSLClientSocket::Write(), which can
12673 // enqueue application data to be sent in the same packet as the
12674 // ChangeCipherSpec and Finished messages.
12675 // The actual handshake will be finished when SSLClientSocket::Read() is
12676 // called, which expects to process the peer's ChangeCipherSpec and
12677 // Finished messages. If there was an error negotiating with the peer,
12678 // such as due to the peer requiring a client certificate when none was
12679 // supplied, the alert sent by the peer won't be processed until Read() is
12680 // called.
12681
12682 // Like the non-False Start case, when a client certificate is requested by
12683 // the peer, the handshake is aborted during the Connect() call.
12684 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2912685 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012686 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712687 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912688 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712689 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012690
12691 // When a client certificate is supplied, Connect() will not be aborted
12692 // when the peer requests the certificate. Instead, the handshake will
12693 // artificially succeed, allowing the caller to write the HTTP request to
12694 // the socket. The handshake messages are not processed until Read() is
12695 // called, which then detects that the handshake was aborted, due to the
12696 // peer sending a handshake_failure because it requires a client
12697 // certificate.
ttuttle859dc7a2015-04-23 19:42:2912698 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012699 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712700 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912701 MockRead data2_reads[] = {
12702 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3012703 };
ttuttle859dc7a2015-04-23 19:42:2912704 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712705 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012706
12707 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1712708 // the data for the SSL handshake once the TLSv1.1 connection falls back to
12709 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912710 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012711 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712712 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912713 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712714 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012715
[email protected]80c75f682012-05-26 16:22:1712716 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
12717 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912718 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1712719 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712720 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912721 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712722 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712723
[email protected]7799de12013-05-30 05:52:5112724 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2912725 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5112726 ssl_data5.cert_request_info = cert_request.get();
12727 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
ttuttle859dc7a2015-04-23 19:42:2912728 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]7799de12013-05-30 05:52:5112729 session_deps_.socket_factory->AddSocketDataProvider(&data5);
12730
mmenkee65e7af2015-10-13 17:16:4212731 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]262eec82013-03-19 21:01:3612732 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012733 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012734
[email protected]bd0b6772011-01-11 19:59:3012735 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4112736 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912737 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12738 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012739
12740 // Complete the SSL handshake, which should abort due to requiring a
12741 // client certificate.
12742 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912743 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]bd0b6772011-01-11 19:59:3012744
12745 // Indicate that no certificate should be supplied. From the perspective
12746 // of SSLClientCertCache, NULL is just as meaningful as a real
12747 // certificate, so this is the same as supply a
12748 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412749 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912750 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]bd0b6772011-01-11 19:59:3012751
12752 // Ensure the certificate was added to the client auth cache before
12753 // allowing the connection to continue restarting.
12754 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412755 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112756 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412757 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012758 ASSERT_EQ(NULL, client_cert.get());
12759
[email protected]bd0b6772011-01-11 19:59:3012760 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712761 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12762 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012763 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912764 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
[email protected]bd0b6772011-01-11 19:59:3012765
12766 // Ensure that the client certificate is removed from the cache on a
12767 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112768 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412769 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012770}
12771
[email protected]8c405132011-01-11 22:03:1812772// Ensure that a client certificate is removed from the SSL client auth
12773// cache when:
12774// 1) An HTTPS proxy is involved.
12775// 3) The HTTPS proxy requests a client certificate.
12776// 4) The client supplies an invalid/unacceptable certificate for the
12777// proxy.
12778// The test is repeated twice, first for connecting to an HTTPS endpoint,
12779// then for connecting to an HTTP endpoint.
[email protected]23e482282013-06-14 16:08:0212780TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
rdsmith82957ad2015-09-16 19:42:0312781 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:5112782 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712783 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1812784
12785 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112786 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1812787
12788 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
12789 // [ssl_]data[1-3]. Rather than represending the endpoint
12790 // (www.example.com:443), they represent failures with the HTTPS proxy
12791 // (proxy:70).
ttuttle859dc7a2015-04-23 19:42:2912792 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8c405132011-01-11 22:03:1812793 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712794 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912795 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712796 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1812797
ttuttle859dc7a2015-04-23 19:42:2912798 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812799 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712800 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912801 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712802 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8c405132011-01-11 22:03:1812803
[email protected]80c75f682012-05-26 16:22:1712804 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
12805#if 0
ttuttle859dc7a2015-04-23 19:42:2912806 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812807 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712808 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912809 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712810 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]80c75f682012-05-26 16:22:1712811#endif
[email protected]8c405132011-01-11 22:03:1812812
ttuttle859dc7a2015-04-23 19:42:2912813 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1812814 requests[0].url = GURL("https://www.example.com/");
12815 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912816 requests[0].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812817
12818 requests[1].url = GURL("http://www.example.com/");
12819 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912820 requests[1].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812821
12822 for (size_t i = 0; i < arraysize(requests); ++i) {
[email protected]bb88e1d32013-05-03 23:11:0712823 session_deps_.socket_factory->ResetNextMockIndexes();
mmenkee65e7af2015-10-13 17:16:4212824 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c405132011-01-11 22:03:1812825 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5012826 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c405132011-01-11 22:03:1812827
12828 // Begin the SSL handshake with the proxy.
[email protected]49639fa2011-12-20 23:22:4112829 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912830 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
12831 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]8c405132011-01-11 22:03:1812832
12833 // Complete the SSL handshake, which should abort due to requiring a
12834 // client certificate.
12835 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912836 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
[email protected]8c405132011-01-11 22:03:1812837
12838 // Indicate that no certificate should be supplied. From the perspective
12839 // of SSLClientCertCache, NULL is just as meaningful as a real
12840 // certificate, so this is the same as supply a
12841 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412842 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
ttuttle859dc7a2015-04-23 19:42:2912843 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]8c405132011-01-11 22:03:1812844
12845 // Ensure the certificate was added to the client auth cache before
12846 // allowing the connection to continue restarting.
12847 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412848 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112849 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412850 HostPortPair("proxy", 70), &client_cert, &client_private_key));
[email protected]8c405132011-01-11 22:03:1812851 ASSERT_EQ(NULL, client_cert.get());
12852 // Ensure the certificate was NOT cached for the endpoint. This only
12853 // applies to HTTPS requests, but is fine to check for HTTP requests.
[email protected]791879c2013-12-17 07:22:4112854 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412855 HostPortPair("www.example.com", 443), &client_cert,
12856 &client_private_key));
[email protected]8c405132011-01-11 22:03:1812857
12858 // Restart the handshake. This will consume ssl_data2, which fails, and
12859 // then consume ssl_data3, which should also fail. The result code is
12860 // checked against what ssl_data3 should return.
12861 rv = callback.WaitForResult();
ttuttle859dc7a2015-04-23 19:42:2912862 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]8c405132011-01-11 22:03:1812863
12864 // Now that the new handshake has failed, ensure that the client
12865 // certificate was removed from the client auth cache.
[email protected]791879c2013-12-17 07:22:4112866 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412867 HostPortPair("proxy", 70), &client_cert, &client_private_key));
[email protected]791879c2013-12-17 07:22:4112868 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412869 HostPortPair("www.example.com", 443), &client_cert,
12870 &client_private_key));
[email protected]8c405132011-01-11 22:03:1812871 }
12872}
12873
mmenke5c642132015-06-02 16:05:1312874TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
bncf33fb31b2016-01-29 15:22:2612875 session_deps_.parse_alternative_services = true;
12876 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]e3ceb682011-06-28 23:55:4612877
12878 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712879 session_deps_.host_resolver.reset(new MockCachingHostResolver());
mmenkee65e7af2015-10-13 17:16:4212880 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2612881 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12882 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4612883
[email protected]8ddf8322012-02-23 18:08:0612884 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812885 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712886 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4612887
[email protected]cdf8f7e72013-05-23 10:56:4612888 scoped_ptr<SpdyFrame> host1_req(
bnc38dcd392016-02-09 23:19:4912889 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812890 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4612891 scoped_ptr<SpdyFrame> host2_req(
bnc38dcd392016-02-09 23:19:4912892 spdy_util_.ConstructSpdyGet("https://www.gmail.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4612893 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312894 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4612895 };
[email protected]23e482282013-06-14 16:08:0212896 scoped_ptr<SpdyFrame> host1_resp(
12897 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12898 scoped_ptr<SpdyFrame> host1_resp_body(
12899 spdy_util_.ConstructSpdyBodyFrame(1, true));
12900 scoped_ptr<SpdyFrame> host2_resp(
12901 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12902 scoped_ptr<SpdyFrame> host2_resp_body(
12903 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4612904 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1312905 CreateMockRead(*host1_resp, 1),
12906 CreateMockRead(*host1_resp_body, 2),
12907 CreateMockRead(*host2_resp, 4),
12908 CreateMockRead(*host2_resp_body, 5),
12909 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4612910 };
12911
eroman36d84e54432016-03-17 03:23:0212912 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0212913 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312914 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12915 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712916 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4612917
[email protected]aa22b242011-11-16 18:58:2912918 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4612919 HttpRequestInfo request1;
12920 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312921 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4612922 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012923 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612924
[email protected]49639fa2011-12-20 23:22:4112925 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612926 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112927 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612928
12929 const HttpResponseInfo* response = trans1.GetResponseInfo();
12930 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012931 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212932 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612933
12934 std::string response_data;
12935 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
12936 EXPECT_EQ("hello!", response_data);
12937
12938 // Preload www.gmail.com into HostCache.
12939 HostPortPair host_port("www.gmail.com", 443);
[email protected]5109c1952013-08-20 18:44:1012940 HostResolver::RequestInfo resolve_info(host_port);
[email protected]e3ceb682011-06-28 23:55:4612941 AddressList ignored;
[email protected]5109c1952013-08-20 18:44:1012942 rv = session_deps_.host_resolver->Resolve(resolve_info,
12943 DEFAULT_PRIORITY,
12944 &ignored,
12945 callback.callback(),
12946 NULL,
12947 BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:4712948 EXPECT_EQ(ERR_IO_PENDING, rv);
12949 rv = callback.WaitForResult();
12950 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:4612951
12952 HttpRequestInfo request2;
12953 request2.method = "GET";
12954 request2.url = GURL("https://www.gmail.com/");
12955 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012956 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612957
[email protected]49639fa2011-12-20 23:22:4112958 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4612959 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4112960 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4612961
12962 response = trans2.GetResponseInfo();
12963 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5012964 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0212965 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612966 EXPECT_TRUE(response->was_fetched_via_spdy);
12967 EXPECT_TRUE(response->was_npn_negotiated);
12968 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
12969 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4612970}
12971
[email protected]23e482282013-06-14 16:08:0212972TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
bncf33fb31b2016-01-29 15:22:2612973 session_deps_.parse_alternative_services = true;
12974 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]d2b5f092012-06-08 23:55:0212975
12976 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712977 session_deps_.host_resolver.reset(new MockCachingHostResolver());
mmenkee65e7af2015-10-13 17:16:4212978 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0212979 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12980 pool_peer.DisableDomainAuthenticationVerification();
12981
12982 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3812983 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0712984 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]d2b5f092012-06-08 23:55:0212985
[email protected]cdf8f7e72013-05-23 10:56:4612986 scoped_ptr<SpdyFrame> host1_req(
bnc38dcd392016-02-09 23:19:4912987 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812988 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4612989 scoped_ptr<SpdyFrame> host2_req(
bnc38dcd392016-02-09 23:19:4912990 spdy_util_.ConstructSpdyGet("https://www.gmail.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0212991 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1312992 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0212993 };
[email protected]23e482282013-06-14 16:08:0212994 scoped_ptr<SpdyFrame> host1_resp(
12995 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12996 scoped_ptr<SpdyFrame> host1_resp_body(
12997 spdy_util_.ConstructSpdyBodyFrame(1, true));
12998 scoped_ptr<SpdyFrame> host2_resp(
12999 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13000 scoped_ptr<SpdyFrame> host2_resp_body(
13001 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0213002 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1313003 CreateMockRead(*host1_resp, 1),
13004 CreateMockRead(*host1_resp_body, 2),
13005 CreateMockRead(*host2_resp, 4),
13006 CreateMockRead(*host2_resp_body, 5),
13007 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0213008 };
13009
eroman36d84e54432016-03-17 03:23:0213010 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0213011 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1313012 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
13013 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0713014 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0213015
13016 TestCompletionCallback callback;
13017 HttpRequestInfo request1;
13018 request1.method = "GET";
bncce36dca22015-04-21 22:11:2313019 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0213020 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013021 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0213022
13023 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
13024 EXPECT_EQ(ERR_IO_PENDING, rv);
13025 EXPECT_EQ(OK, callback.WaitForResult());
13026
13027 const HttpResponseInfo* response = trans1.GetResponseInfo();
13028 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013029 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0213030 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0213031
13032 std::string response_data;
13033 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
13034 EXPECT_EQ("hello!", response_data);
13035
13036 HttpRequestInfo request2;
13037 request2.method = "GET";
13038 request2.url = GURL("https://www.gmail.com/");
13039 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013040 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0213041
13042 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
13043 EXPECT_EQ(ERR_IO_PENDING, rv);
13044 EXPECT_EQ(OK, callback.WaitForResult());
13045
13046 response = trans2.GetResponseInfo();
13047 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013048 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0213049 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0213050 EXPECT_TRUE(response->was_fetched_via_spdy);
13051 EXPECT_TRUE(response->was_npn_negotiated);
13052 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
13053 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0213054}
13055
ttuttle859dc7a2015-04-23 19:42:2913056class OneTimeCachingHostResolver : public HostResolver {
[email protected]e3ceb682011-06-28 23:55:4613057 public:
13058 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
13059 : host_port_(host_port) {}
dchengb03027d2014-10-21 12:00:2013060 ~OneTimeCachingHostResolver() override {}
[email protected]e3ceb682011-06-28 23:55:4613061
13062 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
13063
13064 // HostResolver methods:
dchengb03027d2014-10-21 12:00:2013065 int Resolve(const RequestInfo& info,
13066 RequestPriority priority,
13067 AddressList* addresses,
13068 const CompletionCallback& callback,
13069 RequestHandle* out_req,
13070 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4013071 return host_resolver_.Resolve(
[email protected]5109c1952013-08-20 18:44:1013072 info, priority, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:4013073 }
13074
dchengb03027d2014-10-21 12:00:2013075 int ResolveFromCache(const RequestInfo& info,
13076 AddressList* addresses,
13077 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4013078 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
13079 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]98e1cd012011-11-08 15:33:0913080 host_resolver_.GetHostCache()->clear();
[email protected]e3ceb682011-06-28 23:55:4613081 return rv;
13082 }
13083
dchengb03027d2014-10-21 12:00:2013084 void CancelRequest(RequestHandle req) override {
[email protected]e3ceb682011-06-28 23:55:4613085 host_resolver_.CancelRequest(req);
13086 }
13087
[email protected]46da33be2011-07-19 21:58:0413088 MockCachingHostResolver* GetMockHostResolver() {
13089 return &host_resolver_;
13090 }
13091
[email protected]e3ceb682011-06-28 23:55:4613092 private:
13093 MockCachingHostResolver host_resolver_;
13094 const HostPortPair host_port_;
13095};
13096
mmenke5c642132015-06-02 16:05:1313097TEST_P(HttpNetworkTransactionTest,
13098 UseIPConnectionPoolingWithHostCacheExpiration) {
bncf33fb31b2016-01-29 15:22:2613099 session_deps_.parse_alternative_services = true;
13100 session_deps_.enable_alternative_service_with_different_host = false;
[email protected]e3ceb682011-06-28 23:55:4613101
13102 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
[email protected]e3ceb682011-06-28 23:55:4613103 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
[email protected]c6bf8152012-12-02 07:43:3413104 HttpNetworkSession::Params params =
[email protected]bb88e1d32013-05-03 23:11:0713105 SpdySessionDependencies::CreateSessionParams(&session_deps_);
[email protected]e3ceb682011-06-28 23:55:4613106 params.host_resolver = &host_resolver;
mmenkee65e7af2015-10-13 17:16:4213107 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2613108 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
13109 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4613110
[email protected]8ddf8322012-02-23 18:08:0613111 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813112 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713113 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4613114
[email protected]cdf8f7e72013-05-23 10:56:4613115 scoped_ptr<SpdyFrame> host1_req(
bnc38dcd392016-02-09 23:19:4913116 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3813117 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]cdf8f7e72013-05-23 10:56:4613118 scoped_ptr<SpdyFrame> host2_req(
bnc38dcd392016-02-09 23:19:4913119 spdy_util_.ConstructSpdyGet("https://www.gmail.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4613120 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1313121 CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4613122 };
[email protected]23e482282013-06-14 16:08:0213123 scoped_ptr<SpdyFrame> host1_resp(
13124 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13125 scoped_ptr<SpdyFrame> host1_resp_body(
13126 spdy_util_.ConstructSpdyBodyFrame(1, true));
13127 scoped_ptr<SpdyFrame> host2_resp(
13128 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13129 scoped_ptr<SpdyFrame> host2_resp_body(
13130 spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4613131 MockRead spdy_reads[] = {
rch8e6c6c42015-05-01 14:05:1313132 CreateMockRead(*host1_resp, 1),
13133 CreateMockRead(*host1_resp_body, 2),
13134 CreateMockRead(*host2_resp, 4),
13135 CreateMockRead(*host2_resp_body, 5),
13136 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4613137 };
13138
eroman36d84e54432016-03-17 03:23:0213139 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0213140 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1313141 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
13142 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0713143 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4613144
[email protected]aa22b242011-11-16 18:58:2913145 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4613146 HttpRequestInfo request1;
13147 request1.method = "GET";
bncce36dca22015-04-21 22:11:2313148 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4613149 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013150 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4613151
[email protected]49639fa2011-12-20 23:22:4113152 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4613153 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4113154 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4613155
13156 const HttpResponseInfo* response = trans1.GetResponseInfo();
13157 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013158 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0213159 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4613160
13161 std::string response_data;
13162 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
13163 EXPECT_EQ("hello!", response_data);
13164
13165 // Preload cache entries into HostCache.
[email protected]5109c1952013-08-20 18:44:1013166 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
[email protected]e3ceb682011-06-28 23:55:4613167 AddressList ignored;
[email protected]5109c1952013-08-20 18:44:1013168 rv = host_resolver.Resolve(resolve_info,
13169 DEFAULT_PRIORITY,
13170 &ignored,
13171 callback.callback(),
13172 NULL,
13173 BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:4713174 EXPECT_EQ(ERR_IO_PENDING, rv);
13175 rv = callback.WaitForResult();
13176 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:4613177
13178 HttpRequestInfo request2;
13179 request2.method = "GET";
13180 request2.url = GURL("https://www.gmail.com/");
13181 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013182 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4613183
[email protected]49639fa2011-12-20 23:22:4113184 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:4613185 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:4113186 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:4613187
13188 response = trans2.GetResponseInfo();
13189 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5013190 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0213191 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4613192 EXPECT_TRUE(response->was_fetched_via_spdy);
13193 EXPECT_TRUE(response->was_npn_negotiated);
13194 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
13195 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4613196}
13197
[email protected]23e482282013-06-14 16:08:0213198TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2313199 const std::string https_url = "https://www.example.org:8080/";
13200 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0413201
13202 // SPDY GET for HTTPS URL
[email protected]cdf8f7e72013-05-23 10:56:4613203 scoped_ptr<SpdyFrame> req1(
bnc38dcd392016-02-09 23:19:4913204 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0413205
13206 MockWrite writes1[] = {
13207 CreateMockWrite(*req1, 0),
13208 };
13209
[email protected]23e482282013-06-14 16:08:0213210 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13211 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
mmenkee24011922015-12-17 22:12:5913212 MockRead reads1[] = {CreateMockRead(*resp1, 1), CreateMockRead(*body1, 2),
13213 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0413214
rch8e6c6c42015-05-01 14:05:1313215 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
13216 arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0413217 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5713218 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0413219
13220 // HTTP GET for the HTTP URL
13221 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1313222 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3413223 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2313224 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3413225 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0413226 };
13227
13228 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1313229 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
13230 MockRead(ASYNC, 2, "hello"),
13231 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0413232 };
13233
rch8e6c6c42015-05-01 14:05:1313234 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13235 arraysize(writes2));
[email protected]8450d722012-07-02 19:14:0413236
[email protected]8450d722012-07-02 19:14:0413237 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813238 ssl.SetNextProto(GetProtocol());
[email protected]bb88e1d32013-05-03 23:11:0713239 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13240 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13241 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0413242
mmenkee65e7af2015-10-13 17:16:4213243 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0413244
13245 // Start the first transaction to set up the SpdySession
13246 HttpRequestInfo request1;
13247 request1.method = "GET";
13248 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0413249 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013250 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0413251 TestCompletionCallback callback1;
13252 EXPECT_EQ(ERR_IO_PENDING,
13253 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413254 base::MessageLoop::current()->RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0413255
13256 EXPECT_EQ(OK, callback1.WaitForResult());
13257 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13258
13259 // Now, start the HTTP request
13260 HttpRequestInfo request2;
13261 request2.method = "GET";
13262 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0413263 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013264 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0413265 TestCompletionCallback callback2;
13266 EXPECT_EQ(ERR_IO_PENDING,
13267 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413268 base::MessageLoop::current()->RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0413269
13270 EXPECT_EQ(OK, callback2.WaitForResult());
13271 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13272}
13273
bnc1b0e36852015-04-28 15:32:5913274class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
13275 public:
13276 void Run(bool pooling, bool valid) {
13277 HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org",
13278 443);
13279 HostPortPair alternative("www.example.org", 443);
13280
13281 base::FilePath certs_dir = GetTestCertsDirectory();
13282 scoped_refptr<X509Certificate> cert(
13283 ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
13284 ASSERT_TRUE(cert.get());
13285 bool common_name_fallback_used;
13286 EXPECT_EQ(valid,
13287 cert->VerifyNameMatch(origin.host(), &common_name_fallback_used));
13288 EXPECT_TRUE(
13289 cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used));
13290 SSLSocketDataProvider ssl(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813291 ssl.SetNextProto(GetProtocol());
bnc1b0e36852015-04-28 15:32:5913292 ssl.cert = cert;
13293 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13294
13295 // If pooling, then start a request to alternative first to create a
13296 // SpdySession.
13297 std::string url0 = "https://www.example.org:443";
13298 // Second request to origin, which has an alternative service, and could
13299 // open a connection to the alternative host or pool to the existing one.
13300 std::string url1("https://");
13301 url1.append(origin.host());
13302 url1.append(":443");
13303
13304 scoped_ptr<SpdyFrame> req0;
13305 scoped_ptr<SpdyFrame> req1;
13306 scoped_ptr<SpdyFrame> resp0;
13307 scoped_ptr<SpdyFrame> body0;
13308 scoped_ptr<SpdyFrame> resp1;
13309 scoped_ptr<SpdyFrame> body1;
13310 std::vector<MockWrite> writes;
13311 std::vector<MockRead> reads;
13312
13313 if (pooling) {
bnc38dcd392016-02-09 23:19:4913314 req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3813315 spdy_util_.UpdateWithStreamDestruction(1);
bnc38dcd392016-02-09 23:19:4913316 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), 3, LOWEST));
bnc1b0e36852015-04-28 15:32:5913317
13318 writes.push_back(CreateMockWrite(*req0, 0));
13319 writes.push_back(CreateMockWrite(*req1, 3));
13320
13321 resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13322 body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
13323 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13324 body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true));
13325
13326 reads.push_back(CreateMockRead(*resp0, 1));
13327 reads.push_back(CreateMockRead(*body0, 2));
13328 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4));
13329 reads.push_back(CreateMockRead(*resp1, 5));
13330 reads.push_back(CreateMockRead(*body1, 6));
13331 reads.push_back(MockRead(ASYNC, OK, 7));
13332 } else {
bnc38dcd392016-02-09 23:19:4913333 req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), 1, LOWEST));
bnc1b0e36852015-04-28 15:32:5913334
13335 writes.push_back(CreateMockWrite(*req1, 0));
13336
13337 resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13338 body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true));
13339
13340 reads.push_back(CreateMockRead(*resp1, 1));
13341 reads.push_back(CreateMockRead(*body1, 2));
13342 reads.push_back(MockRead(ASYNC, OK, 3));
13343 }
13344
davidben5f8b6bc2015-11-25 03:19:5413345 SequencedSocketData data(reads.data(), reads.size(), writes.data(),
13346 writes.size());
bnc1b0e36852015-04-28 15:32:5913347 session_deps_.socket_factory->AddSocketDataProvider(&data);
13348
13349 // Connection to the origin fails.
13350 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
13351 StaticSocketDataProvider data_refused;
13352 data_refused.set_connect_data(mock_connect);
13353 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13354
bncf33fb31b2016-01-29 15:22:2613355 session_deps_.parse_alternative_services = true;
13356 session_deps_.enable_alternative_service_with_different_host = true;
mmenkee65e7af2015-10-13 17:16:4213357 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc1b0e36852015-04-28 15:32:5913358 base::WeakPtr<HttpServerProperties> http_server_properties =
13359 session->http_server_properties();
13360 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813361 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213362 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc1b0e36852015-04-28 15:32:5913363 http_server_properties->SetAlternativeService(origin, alternative_service,
rchdc7b9052016-03-17 20:51:5013364 expiration);
bnc1b0e36852015-04-28 15:32:5913365
13366 // First request to alternative.
13367 if (pooling) {
13368 scoped_ptr<HttpTransaction> trans0(
13369 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13370 HttpRequestInfo request0;
13371 request0.method = "GET";
13372 request0.url = GURL(url0);
13373 request0.load_flags = 0;
13374 TestCompletionCallback callback0;
13375
13376 int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog());
13377 EXPECT_EQ(ERR_IO_PENDING, rv);
13378 rv = callback0.WaitForResult();
13379 EXPECT_EQ(OK, rv);
13380 }
13381
13382 // Second request to origin.
13383 scoped_ptr<HttpTransaction> trans1(
13384 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13385 HttpRequestInfo request1;
13386 request1.method = "GET";
13387 request1.url = GURL(url1);
13388 request1.load_flags = 0;
13389 TestCompletionCallback callback1;
13390
13391 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
13392 EXPECT_EQ(ERR_IO_PENDING, rv);
rch32320842015-05-16 15:57:0913393 base::MessageLoop::current()->RunUntilIdle();
mmenkee24011922015-12-17 22:12:5913394 if (data.IsPaused())
13395 data.Resume();
bnc1b0e36852015-04-28 15:32:5913396 rv = callback1.WaitForResult();
13397 if (valid) {
13398 EXPECT_EQ(OK, rv);
13399 } else {
13400 if (pooling) {
13401 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
13402 } else {
13403 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv);
13404 }
13405 }
13406 }
13407};
13408
rdsmithebb50aa2015-11-12 03:44:3813409INSTANTIATE_TEST_CASE_P(ProtoPlusDepend,
bnc1b0e36852015-04-28 15:32:5913410 AltSvcCertificateVerificationTest,
rdsmithebb50aa2015-11-12 03:44:3813411 testing::Values(kTestCaseSPDY31,
13412 kTestCaseHTTP2NoPriorityDependencies,
13413 kTestCaseHTTP2PriorityDependencies));
bnc1b0e36852015-04-28 15:32:5913414
13415// The alternative service host must exhibit a certificate that is valid for the
13416// origin host. Test that this is enforced when pooling to an existing
13417// connection.
13418TEST_P(AltSvcCertificateVerificationTest, PoolingValid) {
13419 Run(true, true);
13420}
13421
13422TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) {
13423 Run(true, false);
13424}
13425
13426// The alternative service host must exhibit a certificate that is valid for the
13427// origin host. Test that this is enforced when opening a new connection.
13428TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) {
13429 Run(false, true);
13430}
13431
13432TEST_P(AltSvcCertificateVerificationTest, NewConnectionInvalid) {
13433 Run(false, false);
13434}
13435
bnc5452e2a2015-05-08 16:27:4213436// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
13437// with the alternative server. That connection should not be used.
13438TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
13439 HostPortPair origin("origin.example.org", 443);
13440 HostPortPair alternative("alternative.example.org", 443);
13441
13442 // Negotiate HTTP/1.1 with alternative.example.org.
13443 SSLSocketDataProvider ssl(ASYNC, OK);
13444 ssl.SetNextProto(kProtoHTTP11);
13445 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13446
13447 // No data should be read from the alternative, because HTTP/1.1 is
13448 // negotiated.
13449 StaticSocketDataProvider data;
13450 session_deps_.socket_factory->AddSocketDataProvider(&data);
13451
13452 // This test documents that an alternate Job should not be used if HTTP/1.1 is
13453 // negotiated. In order to test this, a failed connection to the origin is
13454 // mocked. This way the request relies on the alternate Job.
13455 StaticSocketDataProvider data_refused;
13456 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13457 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13458
13459 // Set up alternative service for origin.
bncf33fb31b2016-01-29 15:22:2613460 session_deps_.parse_alternative_services = true;
13461 session_deps_.enable_alternative_service_with_different_host = true;
mmenkee65e7af2015-10-13 17:16:4213462 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc5452e2a2015-05-08 16:27:4213463 base::WeakPtr<HttpServerProperties> http_server_properties =
13464 session->http_server_properties();
13465 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813466 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213467 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc5452e2a2015-05-08 16:27:4213468 http_server_properties->SetAlternativeService(origin, alternative_service,
rchdc7b9052016-03-17 20:51:5013469 expiration);
bnc5452e2a2015-05-08 16:27:4213470
13471 scoped_ptr<HttpTransaction> trans(
13472 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13473 HttpRequestInfo request;
13474 request.method = "GET";
13475 request.url = GURL("https://origin.example.org:443");
13476 request.load_flags = 0;
13477 TestCompletionCallback callback;
13478
13479 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
13480 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
13481 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13482 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED, callback.GetResult(rv));
13483}
13484
bnc40448a532015-05-11 19:13:1413485// A request to a server with an alternative service fires two Jobs: one to the
13486// origin, and an alternate one to the alternative server. If the former
13487// succeeds, the request should succeed, even if the latter fails because
13488// HTTP/1.1 is negotiated which is insufficient for alternative service.
13489TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
13490 HostPortPair origin("origin.example.org", 443);
13491 HostPortPair alternative("alternative.example.org", 443);
13492
13493 // Negotiate HTTP/1.1 with alternative.
13494 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
13495 alternative_ssl.SetNextProto(kProtoHTTP11);
13496 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
13497
13498 // No data should be read from the alternative, because HTTP/1.1 is
13499 // negotiated.
13500 StaticSocketDataProvider data;
13501 session_deps_.socket_factory->AddSocketDataProvider(&data);
13502
13503 // Negotiate HTTP/1.1 with origin.
13504 SSLSocketDataProvider origin_ssl(ASYNC, OK);
13505 origin_ssl.SetNextProto(kProtoHTTP11);
13506 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
13507
13508 MockWrite http_writes[] = {
13509 MockWrite(
13510 "GET / HTTP/1.1\r\n"
13511 "Host: origin.example.org\r\n"
13512 "Connection: keep-alive\r\n\r\n"),
13513 MockWrite(
13514 "GET /second HTTP/1.1\r\n"
13515 "Host: origin.example.org\r\n"
13516 "Connection: keep-alive\r\n\r\n"),
13517 };
13518
13519 MockRead http_reads[] = {
13520 MockRead("HTTP/1.1 200 OK\r\n"),
13521 MockRead("Content-Type: text/html\r\n"),
13522 MockRead("Content-Length: 6\r\n\r\n"),
13523 MockRead("foobar"),
13524 MockRead("HTTP/1.1 200 OK\r\n"),
13525 MockRead("Content-Type: text/html\r\n"),
13526 MockRead("Content-Length: 7\r\n\r\n"),
13527 MockRead("another"),
13528 };
13529 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13530 http_writes, arraysize(http_writes));
13531 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13532
13533 // Set up alternative service for origin.
bncf33fb31b2016-01-29 15:22:2613534 session_deps_.parse_alternative_services = true;
13535 session_deps_.enable_alternative_service_with_different_host = true;
mmenkee65e7af2015-10-13 17:16:4213536 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc40448a532015-05-11 19:13:1413537 base::WeakPtr<HttpServerProperties> http_server_properties =
13538 session->http_server_properties();
13539 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813540 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213541 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc40448a532015-05-11 19:13:1413542 http_server_properties->SetAlternativeService(origin, alternative_service,
rchdc7b9052016-03-17 20:51:5013543 expiration);
bnc40448a532015-05-11 19:13:1413544
13545 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
13546 HttpRequestInfo request1;
13547 request1.method = "GET";
13548 request1.url = GURL("https://origin.example.org:443");
13549 request1.load_flags = 0;
13550 TestCompletionCallback callback1;
13551
13552 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
13553 rv = callback1.GetResult(rv);
13554 EXPECT_EQ(OK, rv);
13555
13556 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
13557 ASSERT_TRUE(response1 != nullptr);
13558 ASSERT_TRUE(response1->headers.get() != nullptr);
13559 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13560
13561 std::string response_data1;
13562 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data1));
13563 EXPECT_EQ("foobar", response_data1);
13564
13565 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
13566 // for alternative service.
13567 EXPECT_TRUE(
13568 http_server_properties->IsAlternativeServiceBroken(alternative_service));
13569
13570 // Since |alternative_service| is broken, a second transaction to origin
13571 // should not start an alternate Job. It should pool to existing connection
13572 // to origin.
13573 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
13574 HttpRequestInfo request2;
13575 request2.method = "GET";
13576 request2.url = GURL("https://origin.example.org:443/second");
13577 request2.load_flags = 0;
13578 TestCompletionCallback callback2;
13579
13580 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
13581 rv = callback2.GetResult(rv);
13582 EXPECT_EQ(OK, rv);
13583
13584 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
13585 ASSERT_TRUE(response2 != nullptr);
13586 ASSERT_TRUE(response2->headers.get() != nullptr);
13587 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
13588
13589 std::string response_data2;
13590 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data2));
13591 EXPECT_EQ("another", response_data2);
13592}
13593
bnc5452e2a2015-05-08 16:27:4213594// Alternative service requires HTTP/2 (or SPDY), but there is already a
13595// HTTP/1.1 socket open to the alternative server. That socket should not be
13596// used.
13597TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
13598 HostPortPair origin("origin.example.org", 443);
13599 HostPortPair alternative("alternative.example.org", 443);
13600 std::string origin_url = "https://origin.example.org:443";
13601 std::string alternative_url = "https://alternative.example.org:443";
13602
13603 // Negotiate HTTP/1.1 with alternative.example.org.
13604 SSLSocketDataProvider ssl(ASYNC, OK);
13605 ssl.SetNextProto(kProtoHTTP11);
13606 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13607
13608 // HTTP/1.1 data for |request1| and |request2|.
13609 MockWrite http_writes[] = {
13610 MockWrite(
13611 "GET / HTTP/1.1\r\n"
13612 "Host: alternative.example.org\r\n"
13613 "Connection: keep-alive\r\n\r\n"),
13614 MockWrite(
13615 "GET / HTTP/1.1\r\n"
13616 "Host: alternative.example.org\r\n"
13617 "Connection: keep-alive\r\n\r\n"),
13618 };
13619
13620 MockRead http_reads[] = {
13621 MockRead(
13622 "HTTP/1.1 200 OK\r\n"
13623 "Content-Type: text/html; charset=iso-8859-1\r\n"
13624 "Content-Length: 40\r\n\r\n"
13625 "first HTTP/1.1 response from alternative"),
13626 MockRead(
13627 "HTTP/1.1 200 OK\r\n"
13628 "Content-Type: text/html; charset=iso-8859-1\r\n"
13629 "Content-Length: 41\r\n\r\n"
13630 "second HTTP/1.1 response from alternative"),
13631 };
13632 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13633 http_writes, arraysize(http_writes));
13634 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13635
13636 // This test documents that an alternate Job should not pool to an already
13637 // existing HTTP/1.1 connection. In order to test this, a failed connection
13638 // to the origin is mocked. This way |request2| relies on the alternate Job.
13639 StaticSocketDataProvider data_refused;
13640 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13641 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13642
13643 // Set up alternative service for origin.
bncf33fb31b2016-01-29 15:22:2613644 session_deps_.parse_alternative_services = true;
13645 session_deps_.enable_alternative_service_with_different_host = false;
mmenkee65e7af2015-10-13 17:16:4213646 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc5452e2a2015-05-08 16:27:4213647 base::WeakPtr<HttpServerProperties> http_server_properties =
13648 session->http_server_properties();
13649 AlternativeService alternative_service(
rdsmithebb50aa2015-11-12 03:44:3813650 AlternateProtocolFromNextProto(GetProtocol()), alternative);
bnc7dc7e1b42015-07-28 14:43:1213651 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc5452e2a2015-05-08 16:27:4213652 http_server_properties->SetAlternativeService(origin, alternative_service,
rchdc7b9052016-03-17 20:51:5013653 expiration);
bnc5452e2a2015-05-08 16:27:4213654
13655 // First transaction to alternative to open an HTTP/1.1 socket.
13656 scoped_ptr<HttpTransaction> trans1(
13657 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13658 HttpRequestInfo request1;
13659 request1.method = "GET";
13660 request1.url = GURL(alternative_url);
13661 request1.load_flags = 0;
13662 TestCompletionCallback callback1;
13663
13664 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
13665 EXPECT_EQ(OK, callback1.GetResult(rv));
13666 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
13667 ASSERT_TRUE(response1);
13668 ASSERT_TRUE(response1->headers.get());
13669 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13670 EXPECT_TRUE(response1->was_npn_negotiated);
13671 EXPECT_FALSE(response1->was_fetched_via_spdy);
13672 std::string response_data1;
13673 ASSERT_EQ(OK, ReadTransaction(trans1.get(), &response_data1));
13674 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
13675
13676 // Request for origin.example.org, which has an alternative service. This
13677 // will start two Jobs: the alternative looks for connections to pool to,
13678 // finds one which is HTTP/1.1, and should ignore it, and should not try to
13679 // open other connections to alternative server. The Job to origin fails, so
13680 // this request fails.
13681 scoped_ptr<HttpTransaction> trans2(
13682 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13683 HttpRequestInfo request2;
13684 request2.method = "GET";
13685 request2.url = GURL(origin_url);
13686 request2.load_flags = 0;
13687 TestCompletionCallback callback2;
13688
13689 rv = trans2->Start(&request2, callback2.callback(), BoundNetLog());
13690 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback2.GetResult(rv));
13691
13692 // Another transaction to alternative. This is to test that the HTTP/1.1
13693 // socket is still open and in the pool.
13694 scoped_ptr<HttpTransaction> trans3(
13695 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13696 HttpRequestInfo request3;
13697 request3.method = "GET";
13698 request3.url = GURL(alternative_url);
13699 request3.load_flags = 0;
13700 TestCompletionCallback callback3;
13701
13702 rv = trans3->Start(&request3, callback3.callback(), BoundNetLog());
13703 EXPECT_EQ(OK, callback3.GetResult(rv));
13704 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
13705 ASSERT_TRUE(response3);
13706 ASSERT_TRUE(response3->headers.get());
13707 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
13708 EXPECT_TRUE(response3->was_npn_negotiated);
13709 EXPECT_FALSE(response3->was_fetched_via_spdy);
13710 std::string response_data3;
13711 ASSERT_EQ(OK, ReadTransaction(trans3.get(), &response_data3));
13712 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
13713}
13714
[email protected]23e482282013-06-14 16:08:0213715TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2313716 const std::string https_url = "https://www.example.org:8080/";
13717 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0413718
rdsmithebb50aa2015-11-12 03:44:3813719 // Separate SPDY util instance for naked and wrapped requests.
13720 SpdyTestUtil spdy_util_wrapped(GetProtocol(), GetDependenciesFromPriority());
13721
[email protected]8450d722012-07-02 19:14:0413722 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2313723 const HostPortPair host_port_pair("www.example.org", 8080);
lgarrona91df87f2014-12-05 00:51:3413724 scoped_ptr<SpdyFrame> connect(
13725 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
[email protected]cdf8f7e72013-05-23 10:56:4613726 scoped_ptr<SpdyFrame> req1(
bnc38dcd392016-02-09 23:19:4913727 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]23e482282013-06-14 16:08:0213728 scoped_ptr<SpdyFrame> wrapped_req1(
13729 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3913730
13731 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
[email protected]745aa9c2014-06-27 02:21:2913732 SpdyHeaderBlock req2_block;
bnc7ecc1122015-09-28 13:22:4913733 spdy_util_.MaybeAddVersionHeader(&req2_block);
[email protected]745aa9c2014-06-27 02:21:2913734 req2_block[spdy_util_.GetMethodKey()] = "GET";
bncce36dca22015-04-21 22:11:2313735 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
[email protected]745aa9c2014-06-27 02:21:2913736 req2_block[spdy_util_.GetSchemeKey()] = "http";
bnc7ecc1122015-09-28 13:22:4913737 req2_block[spdy_util_.GetPathKey()] = "/";
[email protected]601e03f12014-04-06 16:26:3913738 scoped_ptr<SpdyFrame> req2(
bnc38dcd392016-02-09 23:19:4913739 spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0413740
13741 MockWrite writes1[] = {
mmenke666a6fea2015-12-19 04:16:3313742 CreateMockWrite(*connect, 0), CreateMockWrite(*wrapped_req1, 2),
13743 CreateMockWrite(*req2, 6),
[email protected]8450d722012-07-02 19:14:0413744 };
13745
[email protected]23e482282013-06-14 16:08:0213746 scoped_ptr<SpdyFrame> conn_resp(
bnc38dcd392016-02-09 23:19:4913747 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
13748 scoped_ptr<SpdyFrame> resp1(
13749 spdy_util_wrapped.ConstructSpdyGetSynReply(nullptr, 0, 1));
13750 scoped_ptr<SpdyFrame> body1(
13751 spdy_util_wrapped.ConstructSpdyBodyFrame(1, true));
[email protected]23e482282013-06-14 16:08:0213752 scoped_ptr<SpdyFrame> wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3813753 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
[email protected]23e482282013-06-14 16:08:0213754 scoped_ptr<SpdyFrame> wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3813755 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
[email protected]23e482282013-06-14 16:08:0213756 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13757 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3313758 MockRead reads1[] = {
13759 CreateMockRead(*conn_resp, 1),
13760 MockRead(ASYNC, ERR_IO_PENDING, 3),
13761 CreateMockRead(*wrapped_resp1, 4),
13762 CreateMockRead(*wrapped_body1, 5),
13763 MockRead(ASYNC, ERR_IO_PENDING, 7),
13764 CreateMockRead(*resp2, 8),
13765 CreateMockRead(*body2, 9),
13766 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
13767 };
[email protected]8450d722012-07-02 19:14:0413768
mmenke666a6fea2015-12-19 04:16:3313769 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
13770 arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0413771 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5713772 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0413773
rdsmith82957ad2015-09-16 19:42:0313774 session_deps_.proxy_service =
13775 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:5113776 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0713777 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0413778 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
rdsmithebb50aa2015-11-12 03:44:3813779 ssl1.SetNextProto(GetProtocol());
mmenke666a6fea2015-12-19 04:16:3313780 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0413781 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
rdsmithebb50aa2015-11-12 03:44:3813782 ssl2.SetNextProto(GetProtocol());
mmenke666a6fea2015-12-19 04:16:3313783 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13784 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0413785
mmenke666a6fea2015-12-19 04:16:3313786 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0413787
13788 // Start the first transaction to set up the SpdySession
13789 HttpRequestInfo request1;
13790 request1.method = "GET";
13791 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0413792 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013793 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0413794 TestCompletionCallback callback1;
mmenke666a6fea2015-12-19 04:16:3313795 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
[email protected]8450d722012-07-02 19:14:0413796
mmenke666a6fea2015-12-19 04:16:3313797 // This pause is a hack to avoid running into https://crbug.com/497228.
13798 data1.RunUntilPaused();
13799 base::RunLoop().RunUntilIdle();
13800 data1.Resume();
13801 EXPECT_EQ(OK, callback1.GetResult(rv));
[email protected]8450d722012-07-02 19:14:0413802 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13803
[email protected]f6c63db52013-02-02 00:35:2213804 LoadTimingInfo load_timing_info1;
13805 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
13806 TestLoadTimingNotReusedWithPac(load_timing_info1,
13807 CONNECT_TIMING_HAS_SSL_TIMES);
13808
mmenke666a6fea2015-12-19 04:16:3313809 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0413810 HttpRequestInfo request2;
13811 request2.method = "GET";
13812 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0413813 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013814 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0413815 TestCompletionCallback callback2;
mmenke666a6fea2015-12-19 04:16:3313816 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
[email protected]8450d722012-07-02 19:14:0413817
mmenke666a6fea2015-12-19 04:16:3313818 // This pause is a hack to avoid running into https://crbug.com/497228.
13819 data1.RunUntilPaused();
13820 base::RunLoop().RunUntilIdle();
13821 data1.Resume();
13822 EXPECT_EQ(OK, callback2.GetResult(rv));
13823
[email protected]8450d722012-07-02 19:14:0413824 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2213825
13826 LoadTimingInfo load_timing_info2;
13827 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
13828 // The established SPDY sessions is considered reused by the HTTP request.
13829 TestLoadTimingReusedWithPac(load_timing_info2);
13830 // HTTP requests over a SPDY session should have a different connection
13831 // socket_log_id than requests over a tunnel.
13832 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0413833}
13834
[email protected]2d88e7d2012-07-19 17:55:1713835// Test that in the case where we have a SPDY session to a SPDY proxy
13836// that we do not pool other origins that resolve to the same IP when
13837// the certificate does not match the new origin.
13838// http://crbug.com/134690
[email protected]23e482282013-06-14 16:08:0213839TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2313840 const std::string url1 = "http://www.example.org/";
13841 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1713842 const std::string ip_addr = "1.2.3.4";
13843
rdsmithebb50aa2015-11-12 03:44:3813844 // Second SpdyTestUtil instance for the second socket.
13845 SpdyTestUtil spdy_util_secure(GetProtocol(), GetDependenciesFromPriority());
13846
[email protected]2d88e7d2012-07-19 17:55:1713847 // SPDY GET for HTTP URL (through SPDY proxy)
[email protected]23e482282013-06-14 16:08:0213848 scoped_ptr<SpdyHeaderBlock> headers(
bncce36dca22015-04-21 22:11:2313849 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
[email protected]745aa9c2014-06-27 02:21:2913850 scoped_ptr<SpdyFrame> req1(
bnc38dcd392016-02-09 23:19:4913851 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1713852
13853 MockWrite writes1[] = {
13854 CreateMockWrite(*req1, 0),
13855 };
13856
[email protected]23e482282013-06-14 16:08:0213857 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13858 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1713859 MockRead reads1[] = {
mmenke666a6fea2015-12-19 04:16:3313860 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(*resp1, 2),
13861 CreateMockRead(*body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1713862 };
13863
mmenke666a6fea2015-12-19 04:16:3313864 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
13865 arraysize(writes1));
martijnfe9636e2016-02-06 14:33:3213866 IPAddress ip;
martijn654c8c42016-02-10 22:10:5913867 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1713868 IPEndPoint peer_addr = IPEndPoint(ip, 443);
13869 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3313870 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1713871
13872 // SPDY GET for HTTPS URL (direct)
[email protected]cdf8f7e72013-05-23 10:56:4613873 scoped_ptr<SpdyFrame> req2(
bnc38dcd392016-02-09 23:19:4913874 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1713875
13876 MockWrite writes2[] = {
13877 CreateMockWrite(*req2, 0),
13878 };
13879
rdsmithebb50aa2015-11-12 03:44:3813880 scoped_ptr<SpdyFrame> resp2(
13881 spdy_util_secure.ConstructSpdyGetSynReply(NULL, 0, 1));
13882 scoped_ptr<SpdyFrame> body2(spdy_util_secure.ConstructSpdyBodyFrame(1, true));
mmenke666a6fea2015-12-19 04:16:3313883 MockRead reads2[] = {CreateMockRead(*resp2, 1), CreateMockRead(*body2, 2),
13884 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1713885
mmenke666a6fea2015-12-19 04:16:3313886 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13887 arraysize(writes2));
[email protected]2d88e7d2012-07-19 17:55:1713888 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3313889 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1713890
13891 // Set up a proxy config that sends HTTP requests to a proxy, and
13892 // all others direct.
13893 ProxyConfig proxy_config;
13894 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
[email protected]bb88e1d32013-05-03 23:11:0713895 session_deps_.proxy_service.reset(new ProxyService(
csharrisonb7e3a082015-09-22 19:13:0413896 make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)), nullptr,
13897 NULL));
[email protected]2d88e7d2012-07-19 17:55:1713898
bncce36dca22015-04-21 22:11:2313899 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
rdsmithebb50aa2015-11-12 03:44:3813900 ssl1.SetNextProto(GetProtocol());
[email protected]2d88e7d2012-07-19 17:55:1713901 // Load a valid cert. Note, that this does not need to
13902 // be valid for proxy because the MockSSLClientSocket does
13903 // not actually verify it. But SpdySession will use this
13904 // to see if it is valid for the new origin
bncce36dca22015-04-21 22:11:2313905 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
13906 ASSERT_TRUE(ssl1.cert.get());
mmenke666a6fea2015-12-19 04:16:3313907 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13908 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1713909
13910 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
rdsmithebb50aa2015-11-12 03:44:3813911 ssl2.SetNextProto(GetProtocol());
mmenke666a6fea2015-12-19 04:16:3313912 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13913 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1713914
[email protected]bb88e1d32013-05-03 23:11:0713915 session_deps_.host_resolver.reset(new MockCachingHostResolver());
bncce36dca22015-04-21 22:11:2313916 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0713917 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1713918
mmenke666a6fea2015-12-19 04:16:3313919 scoped_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1713920
13921 // Start the first transaction to set up the SpdySession
13922 HttpRequestInfo request1;
13923 request1.method = "GET";
13924 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1713925 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013926 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713927 TestCompletionCallback callback1;
13928 ASSERT_EQ(ERR_IO_PENDING,
13929 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
mmenke666a6fea2015-12-19 04:16:3313930 // This pause is a hack to avoid running into https://crbug.com/497228.
13931 data1.RunUntilPaused();
13932 base::RunLoop().RunUntilIdle();
13933 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1713934
[email protected]2d88e7d2012-07-19 17:55:1713935 EXPECT_EQ(OK, callback1.WaitForResult());
13936 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13937
13938 // Now, start the HTTP request
13939 HttpRequestInfo request2;
13940 request2.method = "GET";
13941 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1713942 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013943 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713944 TestCompletionCallback callback2;
13945 EXPECT_EQ(ERR_IO_PENDING,
13946 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]2da659e2013-05-23 20:51:3413947 base::MessageLoop::current()->RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1713948
13949 ASSERT_TRUE(callback2.have_result());
13950 EXPECT_EQ(OK, callback2.WaitForResult());
13951 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13952}
13953
[email protected]85f97342013-04-17 06:12:2413954// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
13955// error) in SPDY session, removes the socket from pool and closes the SPDY
13956// session. Verify that new url's from the same HttpNetworkSession (and a new
13957// SpdySession) do work. http://crbug.com/224701
[email protected]23e482282013-06-14 16:08:0213958TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2313959 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2413960
13961 MockRead reads1[] = {
13962 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
13963 };
13964
mmenke11eb5152015-06-09 14:50:5013965 SequencedSocketData data1(reads1, arraysize(reads1), NULL, 0);
[email protected]85f97342013-04-17 06:12:2413966
[email protected]cdf8f7e72013-05-23 10:56:4613967 scoped_ptr<SpdyFrame> req2(
bnc38dcd392016-02-09 23:19:4913968 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2413969 MockWrite writes2[] = {
13970 CreateMockWrite(*req2, 0),
13971 };
13972
[email protected]23e482282013-06-14 16:08:0213973 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13974 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]85f97342013-04-17 06:12:2413975 MockRead reads2[] = {
13976 CreateMockRead(*resp2, 1),
13977 CreateMockRead(*body2, 2),
13978 MockRead(ASYNC, OK, 3) // EOF
13979 };
13980
mmenke11eb5152015-06-09 14:50:5013981 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13982 arraysize(writes2));
[email protected]85f97342013-04-17 06:12:2413983
[email protected]85f97342013-04-17 06:12:2413984 SSLSocketDataProvider ssl1(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813985 ssl1.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:5013986 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13987 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2413988
13989 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3813990 ssl2.SetNextProto(GetProtocol());
mmenke11eb5152015-06-09 14:50:5013991 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13992 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2413993
mmenkee65e7af2015-10-13 17:16:4213994 scoped_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5013995 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2413996
13997 // Start the first transaction to set up the SpdySession and verify that
13998 // connection was closed.
13999 HttpRequestInfo request1;
14000 request1.method = "GET";
14001 request1.url = GURL(https_url);
14002 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5014003 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2414004 TestCompletionCallback callback1;
14005 EXPECT_EQ(ERR_IO_PENDING,
14006 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
[email protected]85f97342013-04-17 06:12:2414007 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
14008
14009 // Now, start the second request and make sure it succeeds.
14010 HttpRequestInfo request2;
14011 request2.method = "GET";
14012 request2.url = GURL(https_url);
14013 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5014014 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2414015 TestCompletionCallback callback2;
14016 EXPECT_EQ(ERR_IO_PENDING,
14017 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]85f97342013-04-17 06:12:2414018
mmenke11eb5152015-06-09 14:50:5014019 ASSERT_EQ(OK, callback2.WaitForResult());
[email protected]85f97342013-04-17 06:12:2414020 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
14021}
14022
[email protected]23e482282013-06-14 16:08:0214023TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0314024 ClientSocketPoolManager::set_max_sockets_per_group(
14025 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14026 ClientSocketPoolManager::set_max_sockets_per_pool(
14027 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14028
14029 // Use two different hosts with different IPs so they don't get pooled.
14030 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
14031 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
mmenkee65e7af2015-10-13 17:16:4214032 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0314033
14034 SSLSocketDataProvider ssl1(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3814035 ssl1.SetNextProto(GetProtocol());
[email protected]483fa202013-05-14 01:07:0314036 SSLSocketDataProvider ssl2(ASYNC, OK);
rdsmithebb50aa2015-11-12 03:44:3814037 ssl2.SetNextProto(GetProtocol());
[email protected]483fa202013-05-14 01:07:0314038 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
14039 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
14040
bnc38dcd392016-02-09 23:19:4914041 scoped_ptr<SpdyFrame> host1_req(
14042 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0314043 MockWrite spdy1_writes[] = {
rch8e6c6c42015-05-01 14:05:1314044 CreateMockWrite(*host1_req, 0),
[email protected]483fa202013-05-14 01:07:0314045 };
[email protected]23e482282013-06-14 16:08:0214046 scoped_ptr<SpdyFrame> host1_resp(
14047 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
14048 scoped_ptr<SpdyFrame> host1_resp_body(
14049 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]483fa202013-05-14 01:07:0314050 MockRead spdy1_reads[] = {
mmenkee24011922015-12-17 22:12:5914051 CreateMockRead(*host1_resp, 1), CreateMockRead(*host1_resp_body, 2),
14052 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0314053 };
14054
rdsmithebb50aa2015-11-12 03:44:3814055 // Use a separate test instance for the separate SpdySession that will be
14056 // created.
14057 SpdyTestUtil spdy_util_2(GetProtocol(), GetDependenciesFromPriority());
rch8e6c6c42015-05-01 14:05:1314058 scoped_ptr<SequencedSocketData> spdy1_data(
14059 new SequencedSocketData(spdy1_reads, arraysize(spdy1_reads), spdy1_writes,
14060 arraysize(spdy1_writes)));
[email protected]483fa202013-05-14 01:07:0314061 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
14062
bnc38dcd392016-02-09 23:19:4914063 scoped_ptr<SpdyFrame> host2_req(
14064 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0314065 MockWrite spdy2_writes[] = {
rch8e6c6c42015-05-01 14:05:1314066 CreateMockWrite(*host2_req, 0),
[email protected]483fa202013-05-14 01:07:0314067 };
[email protected]23e482282013-06-14 16:08:0214068 scoped_ptr<SpdyFrame> host2_resp(
rdsmithebb50aa2015-11-12 03:44:3814069 spdy_util_2.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]23e482282013-06-14 16:08:0214070 scoped_ptr<SpdyFrame> host2_resp_body(
rdsmithebb50aa2015-11-12 03:44:3814071 spdy_util_2.ConstructSpdyBodyFrame(1, true));
[email protected]483fa202013-05-14 01:07:0314072 MockRead spdy2_reads[] = {
mmenkee24011922015-12-17 22:12:5914073 CreateMockRead(*host2_resp, 1), CreateMockRead(*host2_resp_body, 2),
14074 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0314075 };
14076
rch8e6c6c42015-05-01 14:05:1314077 scoped_ptr<SequencedSocketData> spdy2_data(
14078 new SequencedSocketData(spdy2_reads, arraysize(spdy2_reads), spdy2_writes,
14079 arraysize(spdy2_writes)));
[email protected]483fa202013-05-14 01:07:0314080 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
14081
14082 MockWrite http_write[] = {
14083 MockWrite("GET / HTTP/1.1\r\n"
14084 "Host: www.a.com\r\n"
14085 "Connection: keep-alive\r\n\r\n"),
14086 };
14087
14088 MockRead http_read[] = {
14089 MockRead("HTTP/1.1 200 OK\r\n"),
14090 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14091 MockRead("Content-Length: 6\r\n\r\n"),
14092 MockRead("hello!"),
14093 };
14094 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
14095 http_write, arraysize(http_write));
14096 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14097
14098 HostPortPair host_port_pair_a("www.a.com", 443);
[email protected]e6d017652013-05-17 18:01:4014099 SpdySessionKey spdy_session_key_a(
[email protected]314b03992014-04-01 01:28:5314100 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0314101 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614102 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314103
14104 TestCompletionCallback callback;
14105 HttpRequestInfo request1;
14106 request1.method = "GET";
14107 request1.url = GURL("https://www.a.com/");
14108 request1.load_flags = 0;
14109 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5014110 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0314111
14112 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
14113 EXPECT_EQ(ERR_IO_PENDING, rv);
14114 EXPECT_EQ(OK, callback.WaitForResult());
14115
14116 const HttpResponseInfo* response = trans->GetResponseInfo();
14117 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5014118 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0214119 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0314120 EXPECT_TRUE(response->was_fetched_via_spdy);
14121 EXPECT_TRUE(response->was_npn_negotiated);
14122
14123 std::string response_data;
14124 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
14125 EXPECT_EQ("hello!", response_data);
14126 trans.reset();
14127 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2614128 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314129
14130 HostPortPair host_port_pair_b("www.b.com", 443);
[email protected]e6d017652013-05-17 18:01:4014131 SpdySessionKey spdy_session_key_b(
[email protected]314b03992014-04-01 01:28:5314132 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0314133 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614134 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0314135 HttpRequestInfo request2;
14136 request2.method = "GET";
14137 request2.url = GURL("https://www.b.com/");
14138 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5014139 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0314140
14141 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
14142 EXPECT_EQ(ERR_IO_PENDING, rv);
14143 EXPECT_EQ(OK, callback.WaitForResult());
14144
14145 response = trans->GetResponseInfo();
14146 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5014147 ASSERT_TRUE(response->headers.get() != NULL);
bnc84e7fb52015-12-02 11:50:0214148 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0314149 EXPECT_TRUE(response->was_fetched_via_spdy);
14150 EXPECT_TRUE(response->was_npn_negotiated);
14151 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
14152 EXPECT_EQ("hello!", response_data);
14153 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614154 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314155 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2614156 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0314157
14158 HostPortPair host_port_pair_a1("www.a.com", 80);
[email protected]e6d017652013-05-17 18:01:4014159 SpdySessionKey spdy_session_key_a1(
[email protected]314b03992014-04-01 01:28:5314160 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0314161 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614162 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0314163 HttpRequestInfo request3;
14164 request3.method = "GET";
14165 request3.url = GURL("http://www.a.com/");
14166 request3.load_flags = 0;
[email protected]90499482013-06-01 00:39:5014167 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0314168
14169 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
14170 EXPECT_EQ(ERR_IO_PENDING, rv);
14171 EXPECT_EQ(OK, callback.WaitForResult());
14172
14173 response = trans->GetResponseInfo();
14174 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:5014175 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]483fa202013-05-14 01:07:0314176 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14177 EXPECT_FALSE(response->was_fetched_via_spdy);
14178 EXPECT_FALSE(response->was_npn_negotiated);
14179 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
14180 EXPECT_EQ("hello!", response_data);
14181 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614182 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0314183 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2614184 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0314185}
14186
[email protected]79e1fd62013-06-20 06:50:0414187TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
14188 HttpRequestInfo request;
14189 request.method = "GET";
bncce36dca22015-04-21 22:11:2314190 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414191 request.load_flags = 0;
14192
mmenkee65e7af2015-10-13 17:16:4214193 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414194 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114195 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414196
ttuttled9dbc652015-09-29 20:00:5914197 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0414198 StaticSocketDataProvider data;
14199 data.set_connect_data(mock_connect);
14200 session_deps_.socket_factory->AddSocketDataProvider(&data);
14201
14202 TestCompletionCallback callback;
14203
14204 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14205 EXPECT_EQ(ERR_IO_PENDING, rv);
14206
14207 rv = callback.WaitForResult();
ttuttled9dbc652015-09-29 20:00:5914208 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
[email protected]79e1fd62013-06-20 06:50:0414209
[email protected]79e1fd62013-06-20 06:50:0414210 // We don't care whether this succeeds or fails, but it shouldn't crash.
14211 HttpRequestHeaders request_headers;
14212 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4714213
14214 ConnectionAttempts attempts;
14215 trans->GetConnectionAttempts(&attempts);
14216 ASSERT_EQ(1u, attempts.size());
ttuttled9dbc652015-09-29 20:00:5914217 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
14218
14219 IPEndPoint endpoint;
14220 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
14221 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0414222}
14223
14224TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
14225 HttpRequestInfo request;
14226 request.method = "GET";
bncce36dca22015-04-21 22:11:2314227 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414228 request.load_flags = 0;
14229
mmenkee65e7af2015-10-13 17:16:4214230 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414231 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114232 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414233
ttuttled9dbc652015-09-29 20:00:5914234 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0414235 StaticSocketDataProvider data;
14236 data.set_connect_data(mock_connect);
14237 session_deps_.socket_factory->AddSocketDataProvider(&data);
14238
14239 TestCompletionCallback callback;
14240
14241 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14242 EXPECT_EQ(ERR_IO_PENDING, rv);
14243
14244 rv = callback.WaitForResult();
ttuttled9dbc652015-09-29 20:00:5914245 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
[email protected]79e1fd62013-06-20 06:50:0414246
[email protected]79e1fd62013-06-20 06:50:0414247 // We don't care whether this succeeds or fails, but it shouldn't crash.
14248 HttpRequestHeaders request_headers;
14249 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4714250
14251 ConnectionAttempts attempts;
14252 trans->GetConnectionAttempts(&attempts);
14253 ASSERT_EQ(1u, attempts.size());
ttuttled9dbc652015-09-29 20:00:5914254 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
14255
14256 IPEndPoint endpoint;
14257 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
14258 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0414259}
14260
14261TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
14262 HttpRequestInfo request;
14263 request.method = "GET";
bncce36dca22015-04-21 22:11:2314264 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414265 request.load_flags = 0;
14266
mmenkee65e7af2015-10-13 17:16:4214267 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414268 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114269 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414270
14271 MockWrite data_writes[] = {
14272 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14273 };
14274 MockRead data_reads[] = {
14275 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
14276 };
14277
14278 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14279 data_writes, arraysize(data_writes));
14280 session_deps_.socket_factory->AddSocketDataProvider(&data);
14281
14282 TestCompletionCallback callback;
14283
14284 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14285 EXPECT_EQ(ERR_IO_PENDING, rv);
14286
14287 rv = callback.WaitForResult();
14288 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14289
[email protected]79e1fd62013-06-20 06:50:0414290 HttpRequestHeaders request_headers;
14291 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14292 EXPECT_TRUE(request_headers.HasHeader("Host"));
14293}
14294
14295TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
14296 HttpRequestInfo request;
14297 request.method = "GET";
bncce36dca22015-04-21 22:11:2314298 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414299 request.load_flags = 0;
14300
mmenkee65e7af2015-10-13 17:16:4214301 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414302 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114303 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414304
14305 MockWrite data_writes[] = {
14306 MockWrite(ASYNC, ERR_CONNECTION_RESET),
14307 };
14308 MockRead data_reads[] = {
14309 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
14310 };
14311
14312 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14313 data_writes, arraysize(data_writes));
14314 session_deps_.socket_factory->AddSocketDataProvider(&data);
14315
14316 TestCompletionCallback callback;
14317
14318 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14319 EXPECT_EQ(ERR_IO_PENDING, rv);
14320
14321 rv = callback.WaitForResult();
14322 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14323
[email protected]79e1fd62013-06-20 06:50:0414324 HttpRequestHeaders request_headers;
14325 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14326 EXPECT_TRUE(request_headers.HasHeader("Host"));
14327}
14328
14329TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
14330 HttpRequestInfo request;
14331 request.method = "GET";
bncce36dca22015-04-21 22:11:2314332 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414333 request.load_flags = 0;
14334
mmenkee65e7af2015-10-13 17:16:4214335 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414336 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114337 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414338
14339 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314340 MockWrite(
14341 "GET / HTTP/1.1\r\n"
14342 "Host: www.example.org\r\n"
14343 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414344 };
14345 MockRead data_reads[] = {
14346 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
14347 };
14348
14349 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14350 data_writes, arraysize(data_writes));
14351 session_deps_.socket_factory->AddSocketDataProvider(&data);
14352
14353 TestCompletionCallback callback;
14354
14355 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14356 EXPECT_EQ(ERR_IO_PENDING, rv);
14357
14358 rv = callback.WaitForResult();
14359 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14360
[email protected]79e1fd62013-06-20 06:50:0414361 HttpRequestHeaders request_headers;
14362 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14363 EXPECT_TRUE(request_headers.HasHeader("Host"));
14364}
14365
14366TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
14367 HttpRequestInfo request;
14368 request.method = "GET";
bncce36dca22015-04-21 22:11:2314369 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414370 request.load_flags = 0;
14371
mmenkee65e7af2015-10-13 17:16:4214372 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414373 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114374 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414375
14376 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314377 MockWrite(
14378 "GET / HTTP/1.1\r\n"
14379 "Host: www.example.org\r\n"
14380 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414381 };
14382 MockRead data_reads[] = {
14383 MockRead(ASYNC, ERR_CONNECTION_RESET),
14384 };
14385
14386 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14387 data_writes, arraysize(data_writes));
14388 session_deps_.socket_factory->AddSocketDataProvider(&data);
14389
14390 TestCompletionCallback callback;
14391
14392 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14393 EXPECT_EQ(ERR_IO_PENDING, rv);
14394
14395 rv = callback.WaitForResult();
14396 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
14397
[email protected]79e1fd62013-06-20 06:50:0414398 HttpRequestHeaders request_headers;
14399 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14400 EXPECT_TRUE(request_headers.HasHeader("Host"));
14401}
14402
14403TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
14404 HttpRequestInfo request;
14405 request.method = "GET";
bncce36dca22015-04-21 22:11:2314406 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414407 request.load_flags = 0;
14408 request.extra_headers.SetHeader("X-Foo", "bar");
14409
mmenkee65e7af2015-10-13 17:16:4214410 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]79e1fd62013-06-20 06:50:0414411 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114412 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414413
14414 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314415 MockWrite(
14416 "GET / HTTP/1.1\r\n"
14417 "Host: www.example.org\r\n"
14418 "Connection: keep-alive\r\n"
14419 "X-Foo: bar\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414420 };
14421 MockRead data_reads[] = {
14422 MockRead("HTTP/1.1 200 OK\r\n"
14423 "Content-Length: 5\r\n\r\n"
14424 "hello"),
14425 MockRead(ASYNC, ERR_UNEXPECTED),
14426 };
14427
14428 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14429 data_writes, arraysize(data_writes));
14430 session_deps_.socket_factory->AddSocketDataProvider(&data);
14431
14432 TestCompletionCallback callback;
14433
14434 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
14435 EXPECT_EQ(ERR_IO_PENDING, rv);
14436
14437 rv = callback.WaitForResult();
14438 EXPECT_EQ(OK, rv);
14439
14440 HttpRequestHeaders request_headers;
14441 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14442 std::string foo;
14443 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
14444 EXPECT_EQ("bar", foo);
14445}
14446
[email protected]bf828982013-08-14 18:01:4714447namespace {
14448
yhiranoa7e05bb2014-11-06 05:40:3914449// Fake HttpStream that simply records calls to SetPriority().
14450class FakeStream : public HttpStream,
[email protected]e86839fd2013-08-14 18:29:0314451 public base::SupportsWeakPtr<FakeStream> {
14452 public:
14453 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
dchengb03027d2014-10-21 12:00:2014454 ~FakeStream() override {}
[email protected]e86839fd2013-08-14 18:29:0314455
14456 RequestPriority priority() const { return priority_; }
14457
dchengb03027d2014-10-21 12:00:2014458 int InitializeStream(const HttpRequestInfo* request_info,
14459 RequestPriority priority,
14460 const BoundNetLog& net_log,
14461 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314462 return ERR_IO_PENDING;
14463 }
14464
dchengb03027d2014-10-21 12:00:2014465 int SendRequest(const HttpRequestHeaders& request_headers,
14466 HttpResponseInfo* response,
14467 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314468 ADD_FAILURE();
14469 return ERR_UNEXPECTED;
14470 }
14471
dchengb03027d2014-10-21 12:00:2014472 int ReadResponseHeaders(const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314473 ADD_FAILURE();
14474 return ERR_UNEXPECTED;
14475 }
14476
dchengb03027d2014-10-21 12:00:2014477 int ReadResponseBody(IOBuffer* buf,
14478 int buf_len,
14479 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314480 ADD_FAILURE();
14481 return ERR_UNEXPECTED;
14482 }
14483
dchengb03027d2014-10-21 12:00:2014484 void Close(bool not_reusable) override {}
[email protected]e86839fd2013-08-14 18:29:0314485
dchengb03027d2014-10-21 12:00:2014486 bool IsResponseBodyComplete() const override {
[email protected]e86839fd2013-08-14 18:29:0314487 ADD_FAILURE();
14488 return false;
14489 }
14490
dchengb03027d2014-10-21 12:00:2014491 bool IsConnectionReused() const override {
[email protected]e86839fd2013-08-14 18:29:0314492 ADD_FAILURE();
14493 return false;
14494 }
14495
dchengb03027d2014-10-21 12:00:2014496 void SetConnectionReused() override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0314497
mmenkebd84c392015-09-02 14:12:3414498 bool CanReuseConnection() const override { return false; }
[email protected]e86839fd2013-08-14 18:29:0314499
sclittle4de1bab92015-09-22 21:28:2414500 int64_t GetTotalReceivedBytes() const override {
[email protected]bc92bc972013-12-13 08:32:5914501 ADD_FAILURE();
14502 return 0;
14503 }
14504
sclittlebe1ccf62015-09-02 19:40:3614505 int64_t GetTotalSentBytes() const override {
14506 ADD_FAILURE();
14507 return 0;
14508 }
14509
dchengb03027d2014-10-21 12:00:2014510 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
[email protected]e86839fd2013-08-14 18:29:0314511 ADD_FAILURE();
14512 return false;
14513 }
14514
dchengb03027d2014-10-21 12:00:2014515 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
14516
14517 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
[email protected]e86839fd2013-08-14 18:29:0314518 ADD_FAILURE();
14519 }
14520
ttuttled9dbc652015-09-29 20:00:5914521 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
14522
nharperb7441ef2016-01-25 23:54:1414523 Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
14524 std::vector<uint8_t>* out) override {
14525 ADD_FAILURE();
14526 return ERR_NOT_IMPLEMENTED;
14527 }
14528
dchengb03027d2014-10-21 12:00:2014529 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0314530
zhongyica364fbb2015-12-12 03:39:1214531 void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
14532
dchengb03027d2014-10-21 12:00:2014533 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]e86839fd2013-08-14 18:29:0314534
yhiranoa7e05bb2014-11-06 05:40:3914535 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
14536
14537 HttpStream* RenewStreamForAuth() override { return NULL; }
14538
[email protected]e86839fd2013-08-14 18:29:0314539 private:
14540 RequestPriority priority_;
14541
14542 DISALLOW_COPY_AND_ASSIGN(FakeStream);
14543};
14544
14545// Fake HttpStreamRequest that simply records calls to SetPriority()
14546// and vends FakeStreams with its current priority.
[email protected]bf828982013-08-14 18:01:4714547class FakeStreamRequest : public HttpStreamRequest,
14548 public base::SupportsWeakPtr<FakeStreamRequest> {
14549 public:
[email protected]e86839fd2013-08-14 18:29:0314550 FakeStreamRequest(RequestPriority priority,
14551 HttpStreamRequest::Delegate* delegate)
14552 : priority_(priority),
[email protected]831e4a32013-11-14 02:14:4414553 delegate_(delegate),
14554 websocket_stream_create_helper_(NULL) {}
14555
14556 FakeStreamRequest(RequestPriority priority,
14557 HttpStreamRequest::Delegate* delegate,
14558 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
14559 : priority_(priority),
14560 delegate_(delegate),
14561 websocket_stream_create_helper_(create_helper) {}
[email protected]e86839fd2013-08-14 18:29:0314562
dchengb03027d2014-10-21 12:00:2014563 ~FakeStreamRequest() override {}
[email protected]bf828982013-08-14 18:01:4714564
14565 RequestPriority priority() const { return priority_; }
14566
[email protected]831e4a32013-11-14 02:14:4414567 const WebSocketHandshakeStreamBase::CreateHelper*
14568 websocket_stream_create_helper() const {
14569 return websocket_stream_create_helper_;
14570 }
14571
[email protected]e86839fd2013-08-14 18:29:0314572 // Create a new FakeStream and pass it to the request's
14573 // delegate. Returns a weak pointer to the FakeStream.
14574 base::WeakPtr<FakeStream> FinishStreamRequest() {
14575 FakeStream* fake_stream = new FakeStream(priority_);
14576 // Do this before calling OnStreamReady() as OnStreamReady() may
14577 // immediately delete |fake_stream|.
14578 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
14579 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
14580 return weak_stream;
14581 }
14582
dchengb03027d2014-10-21 12:00:2014583 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
[email protected]bf828982013-08-14 18:01:4714584 ADD_FAILURE();
14585 return ERR_UNEXPECTED;
14586 }
14587
dchengb03027d2014-10-21 12:00:2014588 LoadState GetLoadState() const override {
[email protected]bf828982013-08-14 18:01:4714589 ADD_FAILURE();
14590 return LoadState();
14591 }
14592
dchengb03027d2014-10-21 12:00:2014593 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]bf828982013-08-14 18:01:4714594
dchengb03027d2014-10-21 12:00:2014595 bool was_npn_negotiated() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714596
dchengb03027d2014-10-21 12:00:2014597 NextProto protocol_negotiated() const override { return kProtoUnknown; }
[email protected]bf828982013-08-14 18:01:4714598
dchengb03027d2014-10-21 12:00:2014599 bool using_spdy() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714600
ttuttle1f2d7e92015-04-28 16:17:4714601 const ConnectionAttempts& connection_attempts() const override {
14602 static ConnectionAttempts no_attempts;
14603 return no_attempts;
14604 }
14605
[email protected]bf828982013-08-14 18:01:4714606 private:
14607 RequestPriority priority_;
[email protected]e86839fd2013-08-14 18:29:0314608 HttpStreamRequest::Delegate* const delegate_;
[email protected]831e4a32013-11-14 02:14:4414609 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
[email protected]bf828982013-08-14 18:01:4714610
14611 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
14612};
14613
14614// Fake HttpStreamFactory that vends FakeStreamRequests.
14615class FakeStreamFactory : public HttpStreamFactory {
14616 public:
14617 FakeStreamFactory() {}
dchengb03027d2014-10-21 12:00:2014618 ~FakeStreamFactory() override {}
[email protected]bf828982013-08-14 18:01:4714619
14620 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
14621 // RequestStream() (which may be NULL if it was destroyed already).
14622 base::WeakPtr<FakeStreamRequest> last_stream_request() {
14623 return last_stream_request_;
14624 }
14625
dchengb03027d2014-10-21 12:00:2014626 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
14627 RequestPriority priority,
14628 const SSLConfig& server_ssl_config,
14629 const SSLConfig& proxy_ssl_config,
14630 HttpStreamRequest::Delegate* delegate,
14631 const BoundNetLog& net_log) override {
[email protected]e86839fd2013-08-14 18:29:0314632 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
[email protected]bf828982013-08-14 18:01:4714633 last_stream_request_ = fake_request->AsWeakPtr();
14634 return fake_request;
14635 }
14636
xunjieli5749218c2016-03-22 16:43:0614637 HttpStreamRequest* RequestBidirectionalStreamImpl(
xunjieli11834f02015-12-22 04:27:0814638 const HttpRequestInfo& info,
14639 RequestPriority priority,
14640 const SSLConfig& server_ssl_config,
14641 const SSLConfig& proxy_ssl_config,
14642 HttpStreamRequest::Delegate* delegate,
14643 const BoundNetLog& net_log) override {
14644 NOTREACHED();
14645 return nullptr;
14646 }
14647
dchengb03027d2014-10-21 12:00:2014648 HttpStreamRequest* RequestWebSocketHandshakeStream(
[email protected]bf828982013-08-14 18:01:4714649 const HttpRequestInfo& info,
14650 RequestPriority priority,
14651 const SSLConfig& server_ssl_config,
14652 const SSLConfig& proxy_ssl_config,
14653 HttpStreamRequest::Delegate* delegate,
[email protected]467086b2013-11-12 08:19:4614654 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
mostynbba063d6032014-10-09 11:01:1314655 const BoundNetLog& net_log) override {
[email protected]831e4a32013-11-14 02:14:4414656 FakeStreamRequest* fake_request =
14657 new FakeStreamRequest(priority, delegate, create_helper);
14658 last_stream_request_ = fake_request->AsWeakPtr();
14659 return fake_request;
[email protected]bf828982013-08-14 18:01:4714660 }
14661
dchengb03027d2014-10-21 12:00:2014662 void PreconnectStreams(int num_streams,
14663 const HttpRequestInfo& info,
dchengb03027d2014-10-21 12:00:2014664 const SSLConfig& server_ssl_config,
14665 const SSLConfig& proxy_ssl_config) override {
[email protected]bf828982013-08-14 18:01:4714666 ADD_FAILURE();
14667 }
14668
dchengb03027d2014-10-21 12:00:2014669 const HostMappingRules* GetHostMappingRules() const override {
[email protected]bf828982013-08-14 18:01:4714670 ADD_FAILURE();
14671 return NULL;
14672 }
14673
14674 private:
14675 base::WeakPtr<FakeStreamRequest> last_stream_request_;
14676
14677 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
14678};
14679
Adam Rice425cf122015-01-19 06:18:2414680// TODO(ricea): Maybe unify this with the one in
14681// url_request_http_job_unittest.cc ?
14682class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
14683 public:
14684 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection,
14685 bool using_proxy)
14686 : state_(connection.release(), using_proxy) {}
14687
14688 // Fake implementation of HttpStreamBase methods.
14689 // This ends up being quite "real" because this object has to really send data
14690 // on the mock socket. It might be easier to use the real implementation, but
14691 // the fact that the WebSocket code is not compiled on iOS makes that
14692 // difficult.
14693 int InitializeStream(const HttpRequestInfo* request_info,
14694 RequestPriority priority,
14695 const BoundNetLog& net_log,
14696 const CompletionCallback& callback) override {
14697 state_.Initialize(request_info, priority, net_log, callback);
14698 return OK;
14699 }
14700
14701 int SendRequest(const HttpRequestHeaders& request_headers,
14702 HttpResponseInfo* response,
14703 const CompletionCallback& callback) override {
14704 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
14705 response, callback);
14706 }
14707
14708 int ReadResponseHeaders(const CompletionCallback& callback) override {
14709 return parser()->ReadResponseHeaders(callback);
14710 }
14711
14712 int ReadResponseBody(IOBuffer* buf,
14713 int buf_len,
14714 const CompletionCallback& callback) override {
14715 NOTREACHED();
14716 return ERR_IO_PENDING;
14717 }
14718
14719 void Close(bool not_reusable) override {
14720 if (parser())
14721 parser()->Close(true);
14722 }
14723
14724 bool IsResponseBodyComplete() const override {
14725 NOTREACHED();
14726 return false;
14727 }
14728
Adam Rice425cf122015-01-19 06:18:2414729 bool IsConnectionReused() const override {
14730 NOTREACHED();
14731 return false;
14732 }
14733 void SetConnectionReused() override { NOTREACHED(); }
14734
mmenkebd84c392015-09-02 14:12:3414735 bool CanReuseConnection() const override { return false; }
Adam Rice425cf122015-01-19 06:18:2414736
sclittle4de1bab92015-09-22 21:28:2414737 int64_t GetTotalReceivedBytes() const override {
Adam Rice425cf122015-01-19 06:18:2414738 NOTREACHED();
14739 return 0;
14740 }
14741
sclittlebe1ccf62015-09-02 19:40:3614742 int64_t GetTotalSentBytes() const override {
14743 NOTREACHED();
14744 return 0;
14745 }
14746
Adam Rice425cf122015-01-19 06:18:2414747 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
14748 NOTREACHED();
14749 return false;
14750 }
14751
Adam Ricecb76ac62015-02-20 05:33:2514752 void GetSSLInfo(SSLInfo* ssl_info) override {}
Adam Rice425cf122015-01-19 06:18:2414753
14754 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
14755 NOTREACHED();
14756 }
14757
ttuttled9dbc652015-09-29 20:00:5914758 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
14759
nharperb7441ef2016-01-25 23:54:1414760 Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
14761 std::vector<uint8_t>* out) override {
14762 ADD_FAILURE();
14763 return ERR_NOT_IMPLEMENTED;
14764 }
14765
Adam Rice425cf122015-01-19 06:18:2414766 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
14767
zhongyica364fbb2015-12-12 03:39:1214768 void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
14769
Adam Rice425cf122015-01-19 06:18:2414770 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
14771
14772 UploadProgress GetUploadProgress() const override {
14773 NOTREACHED();
14774 return UploadProgress();
14775 }
14776
14777 HttpStream* RenewStreamForAuth() override {
14778 NOTREACHED();
14779 return nullptr;
14780 }
14781
14782 // Fake implementation of WebSocketHandshakeStreamBase method(s)
14783 scoped_ptr<WebSocketStream> Upgrade() override {
14784 NOTREACHED();
14785 return scoped_ptr<WebSocketStream>();
14786 }
14787
14788 private:
14789 HttpStreamParser* parser() const { return state_.parser(); }
14790 HttpBasicState state_;
14791
14792 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
14793};
14794
[email protected]831e4a32013-11-14 02:14:4414795// TODO(yhirano): Split this class out into a net/websockets file, if it is
14796// worth doing.
14797class FakeWebSocketStreamCreateHelper :
14798 public WebSocketHandshakeStreamBase::CreateHelper {
14799 public:
dchengb03027d2014-10-21 12:00:2014800 WebSocketHandshakeStreamBase* CreateBasicStream(
[email protected]7e841a52013-11-22 09:04:2114801 scoped_ptr<ClientSocketHandle> connection,
mostynbba063d6032014-10-09 11:01:1314802 bool using_proxy) override {
dchengc7eeda422015-12-26 03:56:4814803 return new FakeWebSocketBasicHandshakeStream(std::move(connection),
Adam Rice425cf122015-01-19 06:18:2414804 using_proxy);
[email protected]831e4a32013-11-14 02:14:4414805 }
14806
dchengb03027d2014-10-21 12:00:2014807 WebSocketHandshakeStreamBase* CreateSpdyStream(
[email protected]831e4a32013-11-14 02:14:4414808 const base::WeakPtr<SpdySession>& session,
mostynbba063d6032014-10-09 11:01:1314809 bool use_relative_url) override {
[email protected]831e4a32013-11-14 02:14:4414810 NOTREACHED();
14811 return NULL;
14812 };
14813
dchengb03027d2014-10-21 12:00:2014814 ~FakeWebSocketStreamCreateHelper() override {}
[email protected]831e4a32013-11-14 02:14:4414815
14816 virtual scoped_ptr<WebSocketStream> Upgrade() {
14817 NOTREACHED();
14818 return scoped_ptr<WebSocketStream>();
14819 }
14820};
14821
[email protected]bf828982013-08-14 18:01:4714822} // namespace
14823
14824// Make sure that HttpNetworkTransaction passes on its priority to its
14825// stream request on start.
14826TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
mmenkee65e7af2015-10-13 17:16:4214827 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14828 HttpNetworkSessionPeer peer(session.get());
[email protected]bf828982013-08-14 18:01:4714829 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414830 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714831
dcheng48459ac22014-08-26 00:46:4114832 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714833
14834 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
14835
14836 HttpRequestInfo request;
14837 TestCompletionCallback callback;
14838 EXPECT_EQ(ERR_IO_PENDING,
14839 trans.Start(&request, callback.callback(), BoundNetLog()));
14840
14841 base::WeakPtr<FakeStreamRequest> fake_request =
14842 fake_factory->last_stream_request();
14843 ASSERT_TRUE(fake_request != NULL);
14844 EXPECT_EQ(LOW, fake_request->priority());
14845}
14846
14847// Make sure that HttpNetworkTransaction passes on its priority
14848// updates to its stream request.
14849TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
mmenkee65e7af2015-10-13 17:16:4214850 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14851 HttpNetworkSessionPeer peer(session.get());
[email protected]bf828982013-08-14 18:01:4714852 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414853 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714854
dcheng48459ac22014-08-26 00:46:4114855 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714856
14857 HttpRequestInfo request;
14858 TestCompletionCallback callback;
14859 EXPECT_EQ(ERR_IO_PENDING,
14860 trans.Start(&request, callback.callback(), BoundNetLog()));
14861
14862 base::WeakPtr<FakeStreamRequest> fake_request =
14863 fake_factory->last_stream_request();
14864 ASSERT_TRUE(fake_request != NULL);
14865 EXPECT_EQ(LOW, fake_request->priority());
14866
14867 trans.SetPriority(LOWEST);
14868 ASSERT_TRUE(fake_request != NULL);
14869 EXPECT_EQ(LOWEST, fake_request->priority());
14870}
14871
[email protected]e86839fd2013-08-14 18:29:0314872// Make sure that HttpNetworkTransaction passes on its priority
14873// updates to its stream.
14874TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
mmenkee65e7af2015-10-13 17:16:4214875 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14876 HttpNetworkSessionPeer peer(session.get());
[email protected]e86839fd2013-08-14 18:29:0314877 FakeStreamFactory* fake_factory = new FakeStreamFactory();
[email protected]831e4a32013-11-14 02:14:4414878 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
[email protected]e86839fd2013-08-14 18:29:0314879
dcheng48459ac22014-08-26 00:46:4114880 HttpNetworkTransaction trans(LOW, session.get());
[email protected]e86839fd2013-08-14 18:29:0314881
14882 HttpRequestInfo request;
14883 TestCompletionCallback callback;
14884 EXPECT_EQ(ERR_IO_PENDING,
14885 trans.Start(&request, callback.callback(), BoundNetLog()));
14886
14887 base::WeakPtr<FakeStreamRequest> fake_request =
14888 fake_factory->last_stream_request();
14889 ASSERT_TRUE(fake_request != NULL);
14890 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
14891 ASSERT_TRUE(fake_stream != NULL);
14892 EXPECT_EQ(LOW, fake_stream->priority());
14893
14894 trans.SetPriority(LOWEST);
14895 EXPECT_EQ(LOWEST, fake_stream->priority());
14896}
14897
[email protected]831e4a32013-11-14 02:14:4414898TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
14899 // The same logic needs to be tested for both ws: and wss: schemes, but this
14900 // test is already parameterised on NextProto, so it uses a loop to verify
14901 // that the different schemes work.
bncce36dca22015-04-21 22:11:2314902 std::string test_cases[] = {"ws://www.example.org/",
14903 "wss://www.example.org/"};
[email protected]831e4a32013-11-14 02:14:4414904 for (size_t i = 0; i < arraysize(test_cases); ++i) {
mmenkee65e7af2015-10-13 17:16:4214905 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14906 HttpNetworkSessionPeer peer(session.get());
[email protected]831e4a32013-11-14 02:14:4414907 FakeStreamFactory* fake_factory = new FakeStreamFactory();
14908 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
[email protected]0191b51c2013-11-18 10:55:2314909 peer.SetHttpStreamFactoryForWebSocket(
[email protected]831e4a32013-11-14 02:14:4414910 scoped_ptr<HttpStreamFactory>(fake_factory));
14911
dcheng48459ac22014-08-26 00:46:4114912 HttpNetworkTransaction trans(LOW, session.get());
[email protected]831e4a32013-11-14 02:14:4414913 trans.SetWebSocketHandshakeStreamCreateHelper(
14914 &websocket_stream_create_helper);
14915
14916 HttpRequestInfo request;
14917 TestCompletionCallback callback;
14918 request.method = "GET";
14919 request.url = GURL(test_cases[i]);
14920
14921 EXPECT_EQ(ERR_IO_PENDING,
14922 trans.Start(&request, callback.callback(), BoundNetLog()));
14923
14924 base::WeakPtr<FakeStreamRequest> fake_request =
14925 fake_factory->last_stream_request();
14926 ASSERT_TRUE(fake_request != NULL);
14927 EXPECT_EQ(&websocket_stream_create_helper,
14928 fake_request->websocket_stream_create_helper());
14929 }
14930}
14931
[email protected]043b68c82013-08-22 23:41:5214932// Tests that when a used socket is returned to the SSL socket pool, it's closed
14933// if the transport socket pool is stalled on the global socket limit.
14934TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
14935 ClientSocketPoolManager::set_max_sockets_per_group(
14936 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14937 ClientSocketPoolManager::set_max_sockets_per_pool(
14938 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14939
14940 // Set up SSL request.
14941
14942 HttpRequestInfo ssl_request;
14943 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2314944 ssl_request.url = GURL("https://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214945
14946 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2314947 MockWrite(
14948 "GET / HTTP/1.1\r\n"
14949 "Host: www.example.org\r\n"
14950 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214951 };
14952 MockRead ssl_reads[] = {
14953 MockRead("HTTP/1.1 200 OK\r\n"),
14954 MockRead("Content-Length: 11\r\n\r\n"),
14955 MockRead("hello world"),
14956 MockRead(SYNCHRONOUS, OK),
14957 };
14958 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
14959 ssl_writes, arraysize(ssl_writes));
14960 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
14961
14962 SSLSocketDataProvider ssl(ASYNC, OK);
14963 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14964
14965 // Set up HTTP request.
14966
14967 HttpRequestInfo http_request;
14968 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2314969 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214970
14971 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2314972 MockWrite(
14973 "GET / HTTP/1.1\r\n"
14974 "Host: www.example.org\r\n"
14975 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214976 };
14977 MockRead http_reads[] = {
14978 MockRead("HTTP/1.1 200 OK\r\n"),
14979 MockRead("Content-Length: 7\r\n\r\n"),
14980 MockRead("falafel"),
14981 MockRead(SYNCHRONOUS, OK),
14982 };
14983 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
14984 http_writes, arraysize(http_writes));
14985 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14986
mmenkee65e7af2015-10-13 17:16:4214987 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5214988
14989 // Start the SSL request.
14990 TestCompletionCallback ssl_callback;
14991 scoped_ptr<HttpTransaction> ssl_trans(
14992 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14993 ASSERT_EQ(ERR_IO_PENDING,
14994 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
14995 BoundNetLog()));
14996
14997 // Start the HTTP request. Pool should stall.
14998 TestCompletionCallback http_callback;
14999 scoped_ptr<HttpTransaction> http_trans(
15000 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15001 ASSERT_EQ(ERR_IO_PENDING,
15002 http_trans->Start(&http_request, http_callback.callback(),
15003 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4115004 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5215005
15006 // Wait for response from SSL request.
15007 ASSERT_EQ(OK, ssl_callback.WaitForResult());
15008 std::string response_data;
15009 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
15010 EXPECT_EQ("hello world", response_data);
15011
15012 // The SSL socket should automatically be closed, so the HTTP request can
15013 // start.
dcheng48459ac22014-08-26 00:46:4115014 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
15015 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5215016
15017 // The HTTP request can now complete.
15018 ASSERT_EQ(OK, http_callback.WaitForResult());
15019 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
15020 EXPECT_EQ("falafel", response_data);
15021
dcheng48459ac22014-08-26 00:46:4115022 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5215023}
15024
15025// Tests that when a SSL connection is established but there's no corresponding
15026// request that needs it, the new socket is closed if the transport socket pool
15027// is stalled on the global socket limit.
15028TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
15029 ClientSocketPoolManager::set_max_sockets_per_group(
15030 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
15031 ClientSocketPoolManager::set_max_sockets_per_pool(
15032 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
15033
15034 // Set up an ssl request.
15035
15036 HttpRequestInfo ssl_request;
15037 ssl_request.method = "GET";
15038 ssl_request.url = GURL("https://www.foopy.com/");
15039
15040 // No data will be sent on the SSL socket.
15041 StaticSocketDataProvider ssl_data;
15042 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
15043
15044 SSLSocketDataProvider ssl(ASYNC, OK);
15045 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15046
15047 // Set up HTTP request.
15048
15049 HttpRequestInfo http_request;
15050 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2315051 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5215052
15053 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2315054 MockWrite(
15055 "GET / HTTP/1.1\r\n"
15056 "Host: www.example.org\r\n"
15057 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5215058 };
15059 MockRead http_reads[] = {
15060 MockRead("HTTP/1.1 200 OK\r\n"),
15061 MockRead("Content-Length: 7\r\n\r\n"),
15062 MockRead("falafel"),
15063 MockRead(SYNCHRONOUS, OK),
15064 };
15065 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
15066 http_writes, arraysize(http_writes));
15067 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
15068
mmenkee65e7af2015-10-13 17:16:4215069 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5215070
15071 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
15072 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2915073 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
15074 SSLConfig ssl_config;
[email protected]043b68c82013-08-22 23:41:5215075 session->ssl_config_service()->GetSSLConfig(&ssl_config);
mmenked1205bd2015-07-15 22:26:3515076 http_stream_factory->PreconnectStreams(1, ssl_request, ssl_config,
15077 ssl_config);
dcheng48459ac22014-08-26 00:46:4115078 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5215079
15080 // Start the HTTP request. Pool should stall.
15081 TestCompletionCallback http_callback;
15082 scoped_ptr<HttpTransaction> http_trans(
15083 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15084 ASSERT_EQ(ERR_IO_PENDING,
15085 http_trans->Start(&http_request, http_callback.callback(),
15086 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4115087 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5215088
15089 // The SSL connection will automatically be closed once the connection is
15090 // established, to let the HTTP request start.
15091 ASSERT_EQ(OK, http_callback.WaitForResult());
15092 std::string response_data;
15093 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
15094 EXPECT_EQ("falafel", response_data);
15095
dcheng48459ac22014-08-26 00:46:4115096 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5215097}
15098
[email protected]02d74a02014-04-23 18:10:5415099TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215100 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15101 element_readers.push_back(
15102 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15103 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415104
15105 HttpRequestInfo request;
15106 request.method = "POST";
15107 request.url = GURL("http://www.foo.com/");
15108 request.upload_data_stream = &upload_data_stream;
15109 request.load_flags = 0;
15110
mmenkee65e7af2015-10-13 17:16:4215111 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415112 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115113 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415114 // Send headers successfully, but get an error while sending the body.
15115 MockWrite data_writes[] = {
15116 MockWrite("POST / HTTP/1.1\r\n"
15117 "Host: www.foo.com\r\n"
15118 "Connection: keep-alive\r\n"
15119 "Content-Length: 3\r\n\r\n"),
15120 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15121 };
15122
15123 MockRead data_reads[] = {
15124 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15125 MockRead("hello world"),
15126 MockRead(SYNCHRONOUS, OK),
15127 };
15128 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15129 arraysize(data_writes));
15130 session_deps_.socket_factory->AddSocketDataProvider(&data);
15131
15132 TestCompletionCallback callback;
15133
15134 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15135 EXPECT_EQ(ERR_IO_PENDING, rv);
15136
15137 rv = callback.WaitForResult();
15138 EXPECT_EQ(OK, rv);
15139
15140 const HttpResponseInfo* response = trans->GetResponseInfo();
15141 ASSERT_TRUE(response != NULL);
15142
15143 EXPECT_TRUE(response->headers.get() != NULL);
15144 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15145
15146 std::string response_data;
15147 rv = ReadTransaction(trans.get(), &response_data);
15148 EXPECT_EQ(OK, rv);
15149 EXPECT_EQ("hello world", response_data);
15150}
15151
15152// This test makes sure the retry logic doesn't trigger when reading an error
15153// response from a server that rejected a POST with a CONNECTION_RESET.
15154TEST_P(HttpNetworkTransactionTest,
15155 PostReadsErrorResponseAfterResetOnReusedSocket) {
mmenkee65e7af2015-10-13 17:16:4215156 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415157 MockWrite data_writes[] = {
15158 MockWrite("GET / HTTP/1.1\r\n"
15159 "Host: www.foo.com\r\n"
15160 "Connection: keep-alive\r\n\r\n"),
15161 MockWrite("POST / HTTP/1.1\r\n"
15162 "Host: www.foo.com\r\n"
15163 "Connection: keep-alive\r\n"
15164 "Content-Length: 3\r\n\r\n"),
15165 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15166 };
15167
15168 MockRead data_reads[] = {
15169 MockRead("HTTP/1.1 200 Peachy\r\n"
15170 "Content-Length: 14\r\n\r\n"),
15171 MockRead("first response"),
15172 MockRead("HTTP/1.1 400 Not OK\r\n"
15173 "Content-Length: 15\r\n\r\n"),
15174 MockRead("second response"),
15175 MockRead(SYNCHRONOUS, OK),
15176 };
15177 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15178 arraysize(data_writes));
15179 session_deps_.socket_factory->AddSocketDataProvider(&data);
15180
15181 TestCompletionCallback callback;
15182 HttpRequestInfo request1;
15183 request1.method = "GET";
15184 request1.url = GURL("http://www.foo.com/");
15185 request1.load_flags = 0;
15186
15187 scoped_ptr<HttpTransaction> trans1(
dcheng48459ac22014-08-26 00:46:4115188 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415189 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
15190 EXPECT_EQ(ERR_IO_PENDING, rv);
15191
15192 rv = callback.WaitForResult();
15193 EXPECT_EQ(OK, rv);
15194
15195 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
15196 ASSERT_TRUE(response1 != NULL);
15197
15198 EXPECT_TRUE(response1->headers.get() != NULL);
15199 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
15200
15201 std::string response_data1;
15202 rv = ReadTransaction(trans1.get(), &response_data1);
15203 EXPECT_EQ(OK, rv);
15204 EXPECT_EQ("first response", response_data1);
15205 // Delete the transaction to release the socket back into the socket pool.
15206 trans1.reset();
15207
olli.raula6df48b2a2015-11-26 07:40:2215208 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15209 element_readers.push_back(
15210 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15211 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415212
15213 HttpRequestInfo request2;
15214 request2.method = "POST";
15215 request2.url = GURL("http://www.foo.com/");
15216 request2.upload_data_stream = &upload_data_stream;
15217 request2.load_flags = 0;
15218
15219 scoped_ptr<HttpTransaction> trans2(
dcheng48459ac22014-08-26 00:46:4115220 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415221 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
15222 EXPECT_EQ(ERR_IO_PENDING, rv);
15223
15224 rv = callback.WaitForResult();
15225 EXPECT_EQ(OK, rv);
15226
15227 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
15228 ASSERT_TRUE(response2 != NULL);
15229
15230 EXPECT_TRUE(response2->headers.get() != NULL);
15231 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
15232
15233 std::string response_data2;
15234 rv = ReadTransaction(trans2.get(), &response_data2);
15235 EXPECT_EQ(OK, rv);
15236 EXPECT_EQ("second response", response_data2);
15237}
15238
15239TEST_P(HttpNetworkTransactionTest,
15240 PostReadsErrorResponseAfterResetPartialBodySent) {
olli.raula6df48b2a2015-11-26 07:40:2215241 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15242 element_readers.push_back(
15243 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15244 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415245
15246 HttpRequestInfo request;
15247 request.method = "POST";
15248 request.url = GURL("http://www.foo.com/");
15249 request.upload_data_stream = &upload_data_stream;
15250 request.load_flags = 0;
15251
mmenkee65e7af2015-10-13 17:16:4215252 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415253 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115254 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415255 // Send headers successfully, but get an error while sending the body.
15256 MockWrite data_writes[] = {
15257 MockWrite("POST / HTTP/1.1\r\n"
15258 "Host: www.foo.com\r\n"
15259 "Connection: keep-alive\r\n"
15260 "Content-Length: 3\r\n\r\n"
15261 "fo"),
15262 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15263 };
15264
15265 MockRead data_reads[] = {
15266 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15267 MockRead("hello world"),
15268 MockRead(SYNCHRONOUS, OK),
15269 };
15270 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15271 arraysize(data_writes));
15272 session_deps_.socket_factory->AddSocketDataProvider(&data);
15273
15274 TestCompletionCallback callback;
15275
15276 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15277 EXPECT_EQ(ERR_IO_PENDING, rv);
15278
15279 rv = callback.WaitForResult();
15280 EXPECT_EQ(OK, rv);
15281
15282 const HttpResponseInfo* response = trans->GetResponseInfo();
15283 ASSERT_TRUE(response != NULL);
15284
15285 EXPECT_TRUE(response->headers.get() != NULL);
15286 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15287
15288 std::string response_data;
15289 rv = ReadTransaction(trans.get(), &response_data);
15290 EXPECT_EQ(OK, rv);
15291 EXPECT_EQ("hello world", response_data);
15292}
15293
15294// This tests the more common case than the previous test, where headers and
15295// body are not merged into a single request.
15296TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0715297 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5415298
15299 HttpRequestInfo request;
15300 request.method = "POST";
15301 request.url = GURL("http://www.foo.com/");
15302 request.upload_data_stream = &upload_data_stream;
15303 request.load_flags = 0;
15304
mmenkee65e7af2015-10-13 17:16:4215305 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415306 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115307 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415308 // Send headers successfully, but get an error while sending the body.
15309 MockWrite data_writes[] = {
15310 MockWrite("POST / HTTP/1.1\r\n"
15311 "Host: www.foo.com\r\n"
15312 "Connection: keep-alive\r\n"
15313 "Transfer-Encoding: chunked\r\n\r\n"),
15314 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15315 };
15316
15317 MockRead data_reads[] = {
15318 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15319 MockRead("hello world"),
15320 MockRead(SYNCHRONOUS, OK),
15321 };
15322 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15323 arraysize(data_writes));
15324 session_deps_.socket_factory->AddSocketDataProvider(&data);
15325
15326 TestCompletionCallback callback;
15327
15328 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15329 EXPECT_EQ(ERR_IO_PENDING, rv);
15330 // Make sure the headers are sent before adding a chunk. This ensures that
15331 // they can't be merged with the body in a single send. Not currently
15332 // necessary since a chunked body is never merged with headers, but this makes
15333 // the test more future proof.
15334 base::RunLoop().RunUntilIdle();
15335
mmenkecbc2b712014-10-09 20:29:0715336 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5415337
15338 rv = callback.WaitForResult();
15339 EXPECT_EQ(OK, rv);
15340
15341 const HttpResponseInfo* response = trans->GetResponseInfo();
15342 ASSERT_TRUE(response != NULL);
15343
15344 EXPECT_TRUE(response->headers.get() != NULL);
15345 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15346
15347 std::string response_data;
15348 rv = ReadTransaction(trans.get(), &response_data);
15349 EXPECT_EQ(OK, rv);
15350 EXPECT_EQ("hello world", response_data);
15351}
15352
15353TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
olli.raula6df48b2a2015-11-26 07:40:2215354 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15355 element_readers.push_back(
15356 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15357 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415358
15359 HttpRequestInfo request;
15360 request.method = "POST";
15361 request.url = GURL("http://www.foo.com/");
15362 request.upload_data_stream = &upload_data_stream;
15363 request.load_flags = 0;
15364
mmenkee65e7af2015-10-13 17:16:4215365 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415366 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115367 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415368
15369 MockWrite data_writes[] = {
15370 MockWrite("POST / HTTP/1.1\r\n"
15371 "Host: www.foo.com\r\n"
15372 "Connection: keep-alive\r\n"
15373 "Content-Length: 3\r\n\r\n"),
15374 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15375 };
15376
15377 MockRead data_reads[] = {
15378 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
15379 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15380 MockRead("hello world"),
15381 MockRead(SYNCHRONOUS, OK),
15382 };
15383 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15384 arraysize(data_writes));
15385 session_deps_.socket_factory->AddSocketDataProvider(&data);
15386
15387 TestCompletionCallback callback;
15388
15389 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15390 EXPECT_EQ(ERR_IO_PENDING, rv);
15391
15392 rv = callback.WaitForResult();
15393 EXPECT_EQ(OK, rv);
15394
15395 const HttpResponseInfo* response = trans->GetResponseInfo();
15396 ASSERT_TRUE(response != NULL);
15397
15398 EXPECT_TRUE(response->headers.get() != NULL);
15399 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15400
15401 std::string response_data;
15402 rv = ReadTransaction(trans.get(), &response_data);
15403 EXPECT_EQ(OK, rv);
15404 EXPECT_EQ("hello world", response_data);
15405}
15406
15407TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215408 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15409 element_readers.push_back(
15410 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15411 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415412
15413 HttpRequestInfo request;
15414 request.method = "POST";
15415 request.url = GURL("http://www.foo.com/");
15416 request.upload_data_stream = &upload_data_stream;
15417 request.load_flags = 0;
15418
mmenkee65e7af2015-10-13 17:16:4215419 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415420 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115421 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415422 // Send headers successfully, but get an error while sending the body.
15423 MockWrite data_writes[] = {
15424 MockWrite("POST / HTTP/1.1\r\n"
15425 "Host: www.foo.com\r\n"
15426 "Connection: keep-alive\r\n"
15427 "Content-Length: 3\r\n\r\n"),
15428 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15429 };
15430
15431 MockRead data_reads[] = {
15432 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
15433 MockRead("hello world"),
15434 MockRead(SYNCHRONOUS, OK),
15435 };
15436 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15437 arraysize(data_writes));
15438 session_deps_.socket_factory->AddSocketDataProvider(&data);
15439
15440 TestCompletionCallback callback;
15441
15442 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15443 EXPECT_EQ(ERR_IO_PENDING, rv);
15444
15445 rv = callback.WaitForResult();
15446 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415447}
15448
15449TEST_P(HttpNetworkTransactionTest,
15450 PostIgnoresNonErrorResponseAfterResetAnd100) {
olli.raula6df48b2a2015-11-26 07:40:2215451 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15452 element_readers.push_back(
15453 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15454 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415455
15456 HttpRequestInfo request;
15457 request.method = "POST";
15458 request.url = GURL("http://www.foo.com/");
15459 request.upload_data_stream = &upload_data_stream;
15460 request.load_flags = 0;
15461
mmenkee65e7af2015-10-13 17:16:4215462 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415463 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115464 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415465 // Send headers successfully, but get an error while sending the body.
15466 MockWrite data_writes[] = {
15467 MockWrite("POST / HTTP/1.1\r\n"
15468 "Host: www.foo.com\r\n"
15469 "Connection: keep-alive\r\n"
15470 "Content-Length: 3\r\n\r\n"),
15471 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15472 };
15473
15474 MockRead data_reads[] = {
15475 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
15476 MockRead("HTTP/1.0 302 Redirect\r\n"),
15477 MockRead("Location: http://somewhere-else.com/\r\n"),
15478 MockRead("Content-Length: 0\r\n\r\n"),
15479 MockRead(SYNCHRONOUS, OK),
15480 };
15481 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15482 arraysize(data_writes));
15483 session_deps_.socket_factory->AddSocketDataProvider(&data);
15484
15485 TestCompletionCallback callback;
15486
15487 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15488 EXPECT_EQ(ERR_IO_PENDING, rv);
15489
15490 rv = callback.WaitForResult();
15491 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415492}
15493
15494TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215495 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15496 element_readers.push_back(
15497 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15498 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415499
15500 HttpRequestInfo request;
15501 request.method = "POST";
15502 request.url = GURL("http://www.foo.com/");
15503 request.upload_data_stream = &upload_data_stream;
15504 request.load_flags = 0;
15505
mmenkee65e7af2015-10-13 17:16:4215506 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415507 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115508 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415509 // Send headers successfully, but get an error while sending the body.
15510 MockWrite data_writes[] = {
15511 MockWrite("POST / HTTP/1.1\r\n"
15512 "Host: www.foo.com\r\n"
15513 "Connection: keep-alive\r\n"
15514 "Content-Length: 3\r\n\r\n"),
15515 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15516 };
15517
15518 MockRead data_reads[] = {
15519 MockRead("HTTP 0.9 rocks!"),
15520 MockRead(SYNCHRONOUS, OK),
15521 };
15522 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15523 arraysize(data_writes));
15524 session_deps_.socket_factory->AddSocketDataProvider(&data);
15525
15526 TestCompletionCallback callback;
15527
15528 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15529 EXPECT_EQ(ERR_IO_PENDING, rv);
15530
15531 rv = callback.WaitForResult();
15532 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415533}
15534
15535TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
olli.raula6df48b2a2015-11-26 07:40:2215536 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15537 element_readers.push_back(
15538 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15539 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415540
15541 HttpRequestInfo request;
15542 request.method = "POST";
15543 request.url = GURL("http://www.foo.com/");
15544 request.upload_data_stream = &upload_data_stream;
15545 request.load_flags = 0;
15546
mmenkee65e7af2015-10-13 17:16:4215547 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5415548 scoped_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115549 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415550 // Send headers successfully, but get an error while sending the body.
15551 MockWrite data_writes[] = {
15552 MockWrite("POST / HTTP/1.1\r\n"
15553 "Host: www.foo.com\r\n"
15554 "Connection: keep-alive\r\n"
15555 "Content-Length: 3\r\n\r\n"),
15556 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15557 };
15558
15559 MockRead data_reads[] = {
15560 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
15561 MockRead(SYNCHRONOUS, OK),
15562 };
15563 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15564 arraysize(data_writes));
15565 session_deps_.socket_factory->AddSocketDataProvider(&data);
15566
15567 TestCompletionCallback callback;
15568
15569 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15570 EXPECT_EQ(ERR_IO_PENDING, rv);
15571
15572 rv = callback.WaitForResult();
15573 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]02d74a02014-04-23 18:10:5415574}
15575
Adam Rice425cf122015-01-19 06:18:2415576// Verify that proxy headers are not sent to the destination server when
15577// establishing a tunnel for a secure WebSocket connection.
15578TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
15579 HttpRequestInfo request;
15580 request.method = "GET";
bncce36dca22015-04-21 22:11:2315581 request.url = GURL("wss://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 // Since a proxy is configured, try to establish a tunnel.
15591 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1715592 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15593 "Host: www.example.org:443\r\n"
15594 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415595
15596 // After calling trans->RestartWithAuth(), this is the request we should
15597 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1715598 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15599 "Host: www.example.org:443\r\n"
15600 "Proxy-Connection: keep-alive\r\n"
15601 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415602
rsleevidb16bb02015-11-12 23:47:1715603 MockWrite("GET / HTTP/1.1\r\n"
15604 "Host: www.example.org\r\n"
15605 "Connection: Upgrade\r\n"
15606 "Upgrade: websocket\r\n"
15607 "Origin: http://www.example.org\r\n"
15608 "Sec-WebSocket-Version: 13\r\n"
15609 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415610 };
15611
15612 // The proxy responds to the connect with a 407, using a persistent
15613 // connection.
15614 MockRead data_reads[] = {
15615 // No credentials.
15616 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
15617 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
mmenkee71e15332015-10-07 16:39:5415618 MockRead("Content-Length: 0\r\n"),
15619 MockRead("Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415620
15621 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15622
15623 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15624 MockRead("Upgrade: websocket\r\n"),
15625 MockRead("Connection: Upgrade\r\n"),
15626 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15627 };
15628
15629 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15630 arraysize(data_writes));
15631 session_deps_.socket_factory->AddSocketDataProvider(&data);
15632 SSLSocketDataProvider ssl(ASYNC, OK);
15633 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15634
15635 scoped_ptr<HttpTransaction> trans(
15636 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15637 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15638 trans->SetWebSocketHandshakeStreamCreateHelper(
15639 &websocket_stream_create_helper);
15640
15641 {
15642 TestCompletionCallback callback;
15643
15644 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15645 EXPECT_EQ(ERR_IO_PENDING, rv);
15646
15647 rv = callback.WaitForResult();
15648 EXPECT_EQ(OK, rv);
15649 }
15650
15651 const HttpResponseInfo* response = trans->GetResponseInfo();
15652 ASSERT_TRUE(response);
15653 ASSERT_TRUE(response->headers.get());
15654 EXPECT_EQ(407, response->headers->response_code());
15655
15656 {
15657 TestCompletionCallback callback;
15658
15659 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
15660 callback.callback());
15661 EXPECT_EQ(ERR_IO_PENDING, rv);
15662
15663 rv = callback.WaitForResult();
15664 EXPECT_EQ(OK, rv);
15665 }
15666
15667 response = trans->GetResponseInfo();
15668 ASSERT_TRUE(response);
15669 ASSERT_TRUE(response->headers.get());
15670
15671 EXPECT_EQ(101, response->headers->response_code());
15672
15673 trans.reset();
15674 session->CloseAllConnections();
15675}
15676
15677// Verify that proxy headers are not sent to the destination server when
15678// establishing a tunnel for an insecure WebSocket connection.
15679// This requires the authentication info to be injected into the auth cache
15680// due to crbug.com/395064
15681// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
15682TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
15683 HttpRequestInfo request;
15684 request.method = "GET";
bncce36dca22015-04-21 22:11:2315685 request.url = GURL("ws://www.example.org/");
Adam Rice425cf122015-01-19 06:18:2415686 AddWebSocketHeaders(&request.extra_headers);
15687
15688 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:0315689 session_deps_.proxy_service =
15690 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
Adam Rice425cf122015-01-19 06:18:2415691
mmenkee65e7af2015-10-13 17:16:4215692 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2415693
15694 MockWrite data_writes[] = {
15695 // Try to establish a tunnel for the WebSocket connection, with
15696 // credentials. Because WebSockets have a separate set of socket pools,
15697 // they cannot and will not use the same TCP/IP connection as the
15698 // preflight HTTP request.
15699 MockWrite(
bncce36dca22015-04-21 22:11:2315700 "CONNECT www.example.org:80 HTTP/1.1\r\n"
15701 "Host: www.example.org:80\r\n"
Adam Rice425cf122015-01-19 06:18:2415702 "Proxy-Connection: keep-alive\r\n"
15703 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
15704
15705 MockWrite(
15706 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2315707 "Host: www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415708 "Connection: Upgrade\r\n"
15709 "Upgrade: websocket\r\n"
bncce36dca22015-04-21 22:11:2315710 "Origin: http://www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415711 "Sec-WebSocket-Version: 13\r\n"
15712 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
15713 };
15714
15715 MockRead data_reads[] = {
15716 // HTTP CONNECT with credentials.
15717 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15718
15719 // WebSocket connection established inside tunnel.
15720 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15721 MockRead("Upgrade: websocket\r\n"),
15722 MockRead("Connection: Upgrade\r\n"),
15723 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15724 };
15725
15726 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15727 arraysize(data_writes));
15728 session_deps_.socket_factory->AddSocketDataProvider(&data);
15729
15730 session->http_auth_cache()->Add(
15731 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
15732 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
15733
15734 scoped_ptr<HttpTransaction> trans(
15735 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15736 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15737 trans->SetWebSocketHandshakeStreamCreateHelper(
15738 &websocket_stream_create_helper);
15739
15740 TestCompletionCallback callback;
15741
15742 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
15743 EXPECT_EQ(ERR_IO_PENDING, rv);
15744
15745 rv = callback.WaitForResult();
15746 EXPECT_EQ(OK, rv);
15747
15748 const HttpResponseInfo* response = trans->GetResponseInfo();
15749 ASSERT_TRUE(response);
15750 ASSERT_TRUE(response->headers.get());
15751
15752 EXPECT_EQ(101, response->headers->response_code());
15753
15754 trans.reset();
15755 session->CloseAllConnections();
15756}
15757
sclittlefb249892015-09-10 21:33:2215758TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
olli.raula6df48b2a2015-11-26 07:40:2215759 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15760 element_readers.push_back(
15761 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15762 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2215763
15764 HttpRequestInfo request;
15765 request.method = "POST";
15766 request.url = GURL("http://www.foo.com/");
15767 request.upload_data_stream = &upload_data_stream;
15768
mmenkee65e7af2015-10-13 17:16:4215769 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215770 scoped_ptr<HttpTransaction> trans(
15771 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15772 MockWrite data_writes[] = {
15773 MockWrite("POST / HTTP/1.1\r\n"
15774 "Host: www.foo.com\r\n"
15775 "Connection: keep-alive\r\n"
15776 "Content-Length: 3\r\n\r\n"),
15777 MockWrite("foo"),
15778 };
15779
15780 MockRead data_reads[] = {
15781 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15782 MockRead(SYNCHRONOUS, OK),
15783 };
15784 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15785 arraysize(data_writes));
15786 session_deps_.socket_factory->AddSocketDataProvider(&data);
15787
15788 TestCompletionCallback callback;
15789
15790 EXPECT_EQ(ERR_IO_PENDING,
15791 trans->Start(&request, callback.callback(), BoundNetLog()));
15792 EXPECT_EQ(OK, callback.WaitForResult());
15793
15794 std::string response_data;
15795 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15796
15797 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15798 trans->GetTotalSentBytes());
15799 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15800 trans->GetTotalReceivedBytes());
15801}
15802
15803TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
olli.raula6df48b2a2015-11-26 07:40:2215804 std::vector<scoped_ptr<UploadElementReader>> element_readers;
15805 element_readers.push_back(
15806 make_scoped_ptr(new UploadBytesElementReader("foo", 3)));
15807 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2215808
15809 HttpRequestInfo request;
15810 request.method = "POST";
15811 request.url = GURL("http://www.foo.com/");
15812 request.upload_data_stream = &upload_data_stream;
15813
mmenkee65e7af2015-10-13 17:16:4215814 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215815 scoped_ptr<HttpTransaction> trans(
15816 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15817 MockWrite data_writes[] = {
15818 MockWrite("POST / HTTP/1.1\r\n"
15819 "Host: www.foo.com\r\n"
15820 "Connection: keep-alive\r\n"
15821 "Content-Length: 3\r\n\r\n"),
15822 MockWrite("foo"),
15823 };
15824
15825 MockRead data_reads[] = {
15826 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
15827 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15828 MockRead(SYNCHRONOUS, OK),
15829 };
15830 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15831 arraysize(data_writes));
15832 session_deps_.socket_factory->AddSocketDataProvider(&data);
15833
15834 TestCompletionCallback callback;
15835
15836 EXPECT_EQ(ERR_IO_PENDING,
15837 trans->Start(&request, callback.callback(), BoundNetLog()));
15838 EXPECT_EQ(OK, callback.WaitForResult());
15839
15840 std::string response_data;
15841 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15842
15843 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15844 trans->GetTotalSentBytes());
15845 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15846 trans->GetTotalReceivedBytes());
15847}
15848
15849TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2215850 ChunkedUploadDataStream upload_data_stream(0);
15851
15852 HttpRequestInfo request;
15853 request.method = "POST";
15854 request.url = GURL("http://www.foo.com/");
15855 request.upload_data_stream = &upload_data_stream;
15856
mmenkee65e7af2015-10-13 17:16:4215857 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
sclittlefb249892015-09-10 21:33:2215858 scoped_ptr<HttpTransaction> trans(
15859 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15860 // Send headers successfully, but get an error while sending the body.
15861 MockWrite data_writes[] = {
15862 MockWrite("POST / HTTP/1.1\r\n"
15863 "Host: www.foo.com\r\n"
15864 "Connection: keep-alive\r\n"
15865 "Transfer-Encoding: chunked\r\n\r\n"),
15866 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
15867 };
15868
15869 MockRead data_reads[] = {
15870 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15871 MockRead(SYNCHRONOUS, OK),
15872 };
15873 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15874 arraysize(data_writes));
15875 session_deps_.socket_factory->AddSocketDataProvider(&data);
15876
15877 TestCompletionCallback callback;
15878
15879 EXPECT_EQ(ERR_IO_PENDING,
15880 trans->Start(&request, callback.callback(), BoundNetLog()));
15881
15882 base::RunLoop().RunUntilIdle();
15883 upload_data_stream.AppendData("f", 1, false);
15884
15885 base::RunLoop().RunUntilIdle();
15886 upload_data_stream.AppendData("oo", 2, true);
15887
15888 EXPECT_EQ(OK, callback.WaitForResult());
15889
15890 std::string response_data;
15891 EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data));
15892
15893 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15894 trans->GetTotalSentBytes());
15895 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15896 trans->GetTotalReceivedBytes());
15897}
15898
bncf4588402015-11-24 13:33:1815899TEST_P(HttpNetworkTransactionTest, EnableNPN) {
bncf4588402015-11-24 13:33:1815900 session_deps_.enable_npn = true;
15901
15902 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15903 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15904
15905 EXPECT_THAT(trans.server_ssl_config_.alpn_protos,
15906 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15907 EXPECT_THAT(trans.server_ssl_config_.npn_protos,
15908 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15909}
15910
15911TEST_P(HttpNetworkTransactionTest, DisableNPN) {
bncf4588402015-11-24 13:33:1815912 session_deps_.enable_npn = false;
15913
15914 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15915 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15916
15917 EXPECT_THAT(trans.server_ssl_config_.alpn_protos,
15918 testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11));
15919 EXPECT_TRUE(trans.server_ssl_config_.npn_protos.empty());
15920}
15921
nharperb7441ef2016-01-25 23:54:1415922#if !defined(OS_IOS)
15923TEST_P(HttpNetworkTransactionTest, TokenBindingSpdy) {
15924 const std::string https_url = "https://www.example.com";
15925 HttpRequestInfo request;
15926 request.url = GURL(https_url);
15927 request.method = "GET";
15928
15929 SSLSocketDataProvider ssl(ASYNC, OK);
15930 ssl.token_binding_negotiated = true;
15931 ssl.token_binding_key_param = TB_PARAM_ECDSAP256;
15932 ssl.SetNextProto(GetProtocol());
15933 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15934
15935 scoped_ptr<SpdyFrame> resp(
15936 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
15937 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
15938 MockRead reads[] = {CreateMockRead(*resp), CreateMockRead(*body),
15939 MockRead(ASYNC, ERR_IO_PENDING)};
15940 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
15941 session_deps_.socket_factory->AddSocketDataProvider(&data);
15942 session_deps_.channel_id_service.reset(new ChannelIDService(
15943 new DefaultChannelIDStore(nullptr), base::ThreadTaskRunnerHandle::Get()));
15944 scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15945
15946 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15947 TestCompletionCallback callback;
15948 EXPECT_EQ(ERR_IO_PENDING,
15949 trans.Start(&request, callback.callback(), BoundNetLog()));
15950 base::MessageLoop::current()->RunUntilIdle();
15951
15952 EXPECT_TRUE(trans.GetResponseInfo()->was_fetched_via_spdy);
15953 HttpRequestHeaders headers;
15954 ASSERT_TRUE(trans.GetFullRequestHeaders(&headers));
15955 EXPECT_TRUE(headers.HasHeader(HttpRequestHeaders::kTokenBinding));
15956}
15957#endif // !defined(OS_IOS)
15958
[email protected]89ceba9a2009-03-21 03:46:0615959} // namespace net