blob: 976452d9d04c5a54c0c556c1b04ec9a6d02e0606 [file] [log] [blame]
[email protected]95d88ffe2010-02-04 21:25:331// Copyright (c) 2010 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]95d88ffe2010-02-04 21:25:338#include <vector>
[email protected]77848d12008-11-14 00:00:229
[email protected]2d731a32010-04-29 01:04:0610#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3011#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:3312#include "base/file_path.h"
13#include "base/file_util.h"
[email protected]6624b4622010-03-29 19:58:3614#include "base/scoped_ptr.h"
[email protected]169d0012010-05-10 23:20:1215#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3316#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3217#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1218#include "net/base/net_log.h"
19#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3120#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4221#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3322#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5223#include "net/base/test_completion_callback.h"
24#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1225#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0026#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2927#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5728#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5229#include "net/http/http_network_session.h"
[email protected]0877e3d2009-10-17 22:29:5730#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5231#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5332#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1133#include "net/proxy/proxy_resolver.h"
34#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4435#include "net/socket/client_socket_factory.h"
36#include "net/socket/socket_test_util.h"
37#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5438#include "net/spdy/spdy_framer.h"
39#include "net/spdy/spdy_session.h"
40#include "net/spdy/spdy_session_pool.h"
41#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5242#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1543#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5244
45//-----------------------------------------------------------------------------
46
[email protected]89ceba9a2009-03-21 03:46:0647namespace net {
48
[email protected]2d731a32010-04-29 01:04:0649class HttpNetworkSessionPeer {
50 public:
51 explicit HttpNetworkSessionPeer(
52 const scoped_refptr<HttpNetworkSession>& session)
53 : session_(session) {}
54
55 void SetTCPSocketPool(const scoped_refptr<TCPClientSocketPool>& pool) {
56 session_->tcp_socket_pool_ = pool;
57 }
58
59 void SetSocketPoolForSOCKSProxy(
60 const HostPortPair& socks_proxy,
61 const scoped_refptr<SOCKSClientSocketPool>& pool) {
62 session_->socks_socket_pool_[socks_proxy] = pool;
63 }
64
65 void SetSocketPoolForHTTPProxy(
66 const HostPortPair& http_proxy,
[email protected]e772db3f2010-07-12 18:11:1367 const scoped_refptr<HttpProxyClientSocketPool>& pool) {
[email protected]2d731a32010-04-29 01:04:0668 session_->http_proxy_socket_pool_[http_proxy] = pool;
69 }
70
71 private:
72 const scoped_refptr<HttpNetworkSession> session_;
73
74 DISALLOW_COPY_AND_ASSIGN(HttpNetworkSessionPeer);
75};
76
[email protected]e44de5d2009-06-05 20:12:4577// Helper to manage the lifetimes of the dependencies for a
78// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4479struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5980 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4281 SessionDependencies()
82 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:3783 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:1084 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:5285 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]a7ea8832010-07-12 17:54:5486 spdy_session_pool(new SpdySessionPool()),
87 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5988
89 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4590 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4291 : host_resolver(new MockHostResolver),
92 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1093 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:5294 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]a7ea8832010-07-12 17:54:5495 spdy_session_pool(new SpdySessionPool()),
96 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5997
[email protected]a2c2fb92009-07-18 07:31:0498 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0999 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:42100 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:59101 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50102 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a554a8262010-05-20 00:13:52103 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]a7ea8832010-07-12 17:54:54104 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59105};
106
[email protected]1c773ea12009-04-28 19:58:42107ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50108 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48109 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39110 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53111}
112
[email protected]228ff742009-06-05 01:19:59113HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]66761b952010-06-25 21:30:38114 return new HttpNetworkSession(session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:09115 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42116 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10117 session_deps->ssl_config_service,
[email protected]a554a8262010-05-20 00:13:52118 session_deps->spdy_session_pool,
[email protected]06650c52010-06-03 00:49:17119 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44120 NULL,
[email protected]a7ea8832010-07-12 17:54:54121 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14122}
123
[email protected]89836e22008-09-25 20:33:42124class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52125 public:
[email protected]2ff8b312010-04-26 22:20:54126 virtual void SetUp() {
127 spdy::SpdyFramer::set_enable_compression_default(false);
128 }
129
[email protected]0e75a732008-10-16 20:36:09130 virtual void TearDown() {
[email protected]2ff8b312010-04-26 22:20:54131 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09132 // Empty the current queue.
133 MessageLoop::current()->RunAllPending();
134 PlatformTest::TearDown();
135 }
136
[email protected]3d2a59b2008-09-26 19:44:25137 protected:
138 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52139
[email protected]ff007e162009-05-23 09:13:15140 struct SimpleGetHelperResult {
141 int rv;
142 std::string status_line;
143 std::string response_data;
144 };
initial.commit586acc5fe2008-07-26 22:42:52145
[email protected]31a2bfe2010-02-09 08:03:39146 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
147 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15148 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52149
[email protected]228ff742009-06-05 01:19:59150 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40151 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43152 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52153
[email protected]ff007e162009-05-23 09:13:15154 HttpRequestInfo request;
155 request.method = "GET";
156 request.url = GURL("http://www.google.com/");
157 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52158
[email protected]31a2bfe2010-02-09 08:03:39159 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59160 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52161
[email protected]ff007e162009-05-23 09:13:15162 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52163
[email protected]169d0012010-05-10 23:20:12164 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
165 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15166 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52167
[email protected]ff007e162009-05-23 09:13:15168 out.rv = callback.WaitForResult();
169 if (out.rv != OK)
170 return out;
171
172 const HttpResponseInfo* response = trans->GetResponseInfo();
173 EXPECT_TRUE(response != NULL);
174
175 EXPECT_TRUE(response->headers != NULL);
176 out.status_line = response->headers->GetStatusLine();
177
178 rv = ReadTransaction(trans.get(), &out.response_data);
179 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39180 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12181 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
182 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39183 ExpectLogContainsSomewhere(
184 log.entries(), pos,
185 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
186 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15187
[email protected]aecfbf22008-10-16 02:02:47188 return out;
[email protected]ff007e162009-05-23 09:13:15189 }
initial.commit586acc5fe2008-07-26 22:42:52190
[email protected]ff007e162009-05-23 09:13:15191 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
192 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52193
[email protected]ff007e162009-05-23 09:13:15194 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15195};
[email protected]231d5a32008-09-13 00:45:27196
[email protected]15a5ccf82008-10-23 19:57:43197// Fill |str| with a long header list that consumes >= |size| bytes.
198void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19199 const char* row =
200 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
201 const int sizeof_row = strlen(row);
202 const int num_rows = static_cast<int>(
203 ceil(static_cast<float>(size) / sizeof_row));
204 const int sizeof_data = num_rows * sizeof_row;
205 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43206 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51207
[email protected]4ddaf2502008-10-23 18:26:19208 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43209 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19210}
211
[email protected]385a4672009-03-11 22:21:29212// Alternative functions that eliminate randomness and dependency on the local
213// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20214void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29215 static const uint8 bytes[] = {
216 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
217 };
218 static size_t current_byte = 0;
219 for (size_t i = 0; i < n; ++i) {
220 output[i] = bytes[current_byte++];
221 current_byte %= arraysize(bytes);
222 }
223}
224
[email protected]fe2bc6a2009-03-23 16:52:20225void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29226 static const uint8 bytes[] = {
227 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
228 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
229 };
230 static size_t current_byte = 0;
231 for (size_t i = 0; i < n; ++i) {
232 output[i] = bytes[current_byte++];
233 current_byte %= arraysize(bytes);
234 }
235}
236
[email protected]fe2bc6a2009-03-23 16:52:20237std::string MockGetHostName() {
238 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29239}
240
[email protected]2d731a32010-04-29 01:04:06241template<typename EmulatedClientSocketPool>
[email protected]a796bcec2010-03-22 17:17:26242class CaptureGroupNameSocketPool : public EmulatedClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31243 public:
[email protected]06650c52010-06-03 00:49:17244 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session)
[email protected]b89f7e42010-05-20 20:37:00245 : EmulatedClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
[email protected]66761b952010-06-25 21:30:38246 NULL) {
247 }
[email protected]d80a4322009-08-14 07:07:49248 const std::string last_group_name_received() const {
249 return last_group_name_;
250 }
251
[email protected]684970b2009-08-14 04:54:46252 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49253 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31254 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31255 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46256 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53257 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31258 last_group_name_ = group_name;
259 return ERR_IO_PENDING;
260 }
[email protected]04e5be32009-06-26 20:00:31261 virtual void CancelRequest(const std::string& group_name,
262 const ClientSocketHandle* handle) { }
263 virtual void ReleaseSocket(const std::string& group_name,
264 ClientSocket* socket) {}
265 virtual void CloseIdleSockets() {}
266 virtual HostResolver* GetHostResolver() const {
267 return NULL;
268 }
269 virtual int IdleSocketCount() const {
270 return 0;
271 }
272 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
273 return 0;
274 }
275 virtual LoadState GetLoadState(const std::string& group_name,
276 const ClientSocketHandle* handle) const {
277 return LOAD_STATE_IDLE;
278 }
[email protected]a796bcec2010-03-22 17:17:26279 virtual base::TimeDelta ConnectionTimeout() const {
280 return base::TimeDelta();
281 }
[email protected]d80a4322009-08-14 07:07:49282
283 private:
[email protected]04e5be32009-06-26 20:00:31284 std::string last_group_name_;
285};
286
[email protected]2d731a32010-04-29 01:04:06287typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11288CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13289typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
290CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06291typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11292CaptureGroupNameSOCKSSocketPool;
293
[email protected]231d5a32008-09-13 00:45:27294//-----------------------------------------------------------------------------
295
296TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59297 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40298 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43299 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27300}
301
302TEST_F(HttpNetworkTransactionTest, SimpleGET) {
303 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35304 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
305 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42306 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27307 };
[email protected]31a2bfe2010-02-09 08:03:39308 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
309 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42310 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27311 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
312 EXPECT_EQ("hello world", out.response_data);
313}
314
315// Response with no status line.
316TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
317 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35318 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42319 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27320 };
[email protected]31a2bfe2010-02-09 08:03:39321 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
322 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42323 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27324 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
325 EXPECT_EQ("hello world", out.response_data);
326}
327
328// Allow up to 4 bytes of junk to precede status line.
329TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
330 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35331 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42332 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27333 };
[email protected]31a2bfe2010-02-09 08:03:39334 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
335 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42336 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27337 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
338 EXPECT_EQ("DATA", out.response_data);
339}
340
341// Allow up to 4 bytes of junk to precede status line.
342TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
343 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35344 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42345 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27346 };
[email protected]31a2bfe2010-02-09 08:03:39347 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
348 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42349 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27350 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
351 EXPECT_EQ("DATA", out.response_data);
352}
353
354// Beyond 4 bytes of slop and it should fail to find a status line.
355TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
356 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35357 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42358 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27359 };
[email protected]31a2bfe2010-02-09 08:03:39360 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
361 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42362 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25363 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
364 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27365}
366
367// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
368TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
369 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35370 MockRead("\n"),
371 MockRead("\n"),
372 MockRead("Q"),
373 MockRead("J"),
374 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42375 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27376 };
[email protected]31a2bfe2010-02-09 08:03:39377 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
378 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42379 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27380 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
381 EXPECT_EQ("DATA", out.response_data);
382}
383
384// Close the connection before enough bytes to have a status line.
385TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
386 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35387 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42388 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27389 };
[email protected]31a2bfe2010-02-09 08:03:39390 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
391 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42392 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27393 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
394 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52395}
396
[email protected]f9d44aa2008-09-23 23:57:17397// Simulate a 204 response, lacking a Content-Length header, sent over a
398// persistent connection. The response should still terminate since a 204
399// cannot have a response body.
400TEST_F(HttpNetworkTransactionTest, StopsReading204) {
401 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35402 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
403 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42404 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17405 };
[email protected]31a2bfe2010-02-09 08:03:39406 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
407 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42408 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17409 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
410 EXPECT_EQ("", out.response_data);
411}
412
[email protected]0877e3d2009-10-17 22:29:57413// A simple request using chunked encoding with some extra data after.
414// (Like might be seen in a pipelined response.)
415TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
416 MockRead data_reads[] = {
417 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
418 MockRead("5\r\nHello\r\n"),
419 MockRead("1\r\n"),
420 MockRead(" \r\n"),
421 MockRead("5\r\nworld\r\n"),
422 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
423 MockRead(false, OK),
424 };
[email protected]31a2bfe2010-02-09 08:03:39425 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
426 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57427 EXPECT_EQ(OK, out.rv);
428 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
429 EXPECT_EQ("Hello world", out.response_data);
430}
431
[email protected]ef0faf2e72009-03-05 23:27:23432// Do a request using the HEAD method. Verify that we don't try to read the
433// message body (since HEAD has none).
434TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59435 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40436 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43437 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23438
[email protected]1c773ea12009-04-28 19:58:42439 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23440 request.method = "HEAD";
441 request.url = GURL("http://www.google.com/");
442 request.load_flags = 0;
443
444 MockWrite data_writes1[] = {
445 MockWrite("HEAD / HTTP/1.1\r\n"
446 "Host: www.google.com\r\n"
447 "Connection: keep-alive\r\n"
448 "Content-Length: 0\r\n\r\n"),
449 };
450 MockRead data_reads1[] = {
451 MockRead("HTTP/1.1 404 Not Found\r\n"),
452 MockRead("Server: Blah\r\n"),
453 MockRead("Content-Length: 1234\r\n\r\n"),
454
455 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42456 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23457 };
458
[email protected]31a2bfe2010-02-09 08:03:39459 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
460 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59461 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23462
463 TestCompletionCallback callback1;
464
[email protected]5a1d7ca2010-04-28 20:12:27465 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42466 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23467
468 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42469 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23470
[email protected]1c773ea12009-04-28 19:58:42471 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23472 EXPECT_FALSE(response == NULL);
473
474 // Check that the headers got parsed.
475 EXPECT_TRUE(response->headers != NULL);
476 EXPECT_EQ(1234, response->headers->GetContentLength());
477 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
478
479 std::string server_header;
480 void* iter = NULL;
481 bool has_server_header = response->headers->EnumerateHeader(
482 &iter, "Server", &server_header);
483 EXPECT_TRUE(has_server_header);
484 EXPECT_EQ("Blah", server_header);
485
486 // Reading should give EOF right away, since there is no message body
487 // (despite non-zero content-length).
488 std::string response_data;
489 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42490 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23491 EXPECT_EQ("", response_data);
492}
493
initial.commit586acc5fe2008-07-26 22:42:52494TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59495 SessionDependencies session_deps;
496 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52497
498 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35499 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
500 MockRead("hello"),
501 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
502 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42503 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52504 };
[email protected]31a2bfe2010-02-09 08:03:39505 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59506 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52507
508 const char* kExpectedResponseData[] = {
509 "hello", "world"
510 };
511
512 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43513 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52514
[email protected]1c773ea12009-04-28 19:58:42515 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52516 request.method = "GET";
517 request.url = GURL("http://www.google.com/");
518 request.load_flags = 0;
519
520 TestCompletionCallback callback;
521
[email protected]5a1d7ca2010-04-28 20:12:27522 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42523 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52524
525 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42526 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52527
[email protected]1c773ea12009-04-28 19:58:42528 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52529 EXPECT_TRUE(response != NULL);
530
531 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25532 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52533
534 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57535 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42536 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25537 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52538 }
539}
540
541TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59542 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40543 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43544 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52545
[email protected]1c773ea12009-04-28 19:58:42546 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52547 request.method = "POST";
548 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42549 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52550 request.upload_data->AppendBytes("foo", 3);
551 request.load_flags = 0;
552
553 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35554 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
555 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
556 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42557 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52558 };
[email protected]31a2bfe2010-02-09 08:03:39559 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59560 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52561
562 TestCompletionCallback callback;
563
[email protected]5a1d7ca2010-04-28 20:12:27564 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42565 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52566
567 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42568 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52569
[email protected]1c773ea12009-04-28 19:58:42570 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52571 EXPECT_TRUE(response != NULL);
572
573 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25574 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52575
576 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57577 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42578 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25579 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52580}
581
[email protected]3a2d3662009-03-27 03:49:14582// This test is almost the same as Ignores100 above, but the response contains
583// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57584// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14585TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59586 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40587 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43588 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14589
[email protected]1c773ea12009-04-28 19:58:42590 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14591 request.method = "GET";
592 request.url = GURL("http://www.foo.com/");
593 request.load_flags = 0;
594
595 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57596 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
597 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14598 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42599 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14600 };
[email protected]31a2bfe2010-02-09 08:03:39601 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59602 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14603
604 TestCompletionCallback callback;
605
[email protected]5a1d7ca2010-04-28 20:12:27606 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42607 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14608
609 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42610 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14611
[email protected]1c773ea12009-04-28 19:58:42612 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14613 EXPECT_TRUE(response != NULL);
614
615 EXPECT_TRUE(response->headers != NULL);
616 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
617
618 std::string response_data;
619 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42620 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14621 EXPECT_EQ("hello world", response_data);
622}
623
[email protected]ee9410e72010-01-07 01:42:38624TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
625 SessionDependencies session_deps;
626 scoped_ptr<HttpTransaction> trans(
627 new HttpNetworkTransaction(CreateSession(&session_deps)));
628
629 HttpRequestInfo request;
630 request.method = "POST";
631 request.url = GURL("http://www.foo.com/");
632 request.load_flags = 0;
633
634 MockRead data_reads[] = {
635 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
636 MockRead(true, 0),
637 };
[email protected]31a2bfe2010-02-09 08:03:39638 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38639 session_deps.socket_factory.AddSocketDataProvider(&data);
640
641 TestCompletionCallback callback;
642
[email protected]5a1d7ca2010-04-28 20:12:27643 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38644 EXPECT_EQ(ERR_IO_PENDING, rv);
645
646 rv = callback.WaitForResult();
647 EXPECT_EQ(OK, rv);
648
649 std::string response_data;
650 rv = ReadTransaction(trans.get(), &response_data);
651 EXPECT_EQ(OK, rv);
652 EXPECT_EQ("", response_data);
653}
654
655TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
656 SessionDependencies session_deps;
657 scoped_ptr<HttpTransaction> trans(
658 new HttpNetworkTransaction(CreateSession(&session_deps)));
659
660 HttpRequestInfo request;
661 request.method = "POST";
662 request.url = GURL("http://www.foo.com/");
663 request.load_flags = 0;
664
665 MockRead data_reads[] = {
666 MockRead(true, 0),
667 };
[email protected]31a2bfe2010-02-09 08:03:39668 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38669 session_deps.socket_factory.AddSocketDataProvider(&data);
670
671 TestCompletionCallback callback;
672
[email protected]5a1d7ca2010-04-28 20:12:27673 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38674 EXPECT_EQ(ERR_IO_PENDING, rv);
675
676 rv = callback.WaitForResult();
677 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
678}
679
[email protected]3d2a59b2008-09-26 19:44:25680// read_failure specifies a read failure that should cause the network
681// transaction to resend the request.
682void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
683 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59684 SessionDependencies session_deps;
685 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52686
[email protected]1c773ea12009-04-28 19:58:42687 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52688 request.method = "GET";
689 request.url = GURL("http://www.foo.com/");
690 request.load_flags = 0;
691
692 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35693 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
694 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25695 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52696 };
[email protected]31a2bfe2010-02-09 08:03:39697 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59698 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52699
700 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35701 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
702 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42703 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52704 };
[email protected]31a2bfe2010-02-09 08:03:39705 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59706 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52707
708 const char* kExpectedResponseData[] = {
709 "hello", "world"
710 };
711
712 for (int i = 0; i < 2; ++i) {
713 TestCompletionCallback callback;
714
[email protected]5695b8c2009-09-30 21:36:43715 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52716
[email protected]5a1d7ca2010-04-28 20:12:27717 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42718 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52719
720 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42721 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52722
[email protected]1c773ea12009-04-28 19:58:42723 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52724 EXPECT_TRUE(response != NULL);
725
726 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25727 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52728
729 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57730 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42731 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25732 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52733 }
734}
[email protected]3d2a59b2008-09-26 19:44:25735
736TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42737 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25738 KeepAliveConnectionResendRequestTest(read_failure);
739}
740
741TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42742 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25743 KeepAliveConnectionResendRequestTest(read_failure);
744}
745
746TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59747 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40748 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43749 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25750
[email protected]1c773ea12009-04-28 19:58:42751 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25752 request.method = "GET";
753 request.url = GURL("http://www.google.com/");
754 request.load_flags = 0;
755
756 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42757 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35758 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
759 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42760 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25761 };
[email protected]31a2bfe2010-02-09 08:03:39762 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59763 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25764
765 TestCompletionCallback callback;
766
[email protected]5a1d7ca2010-04-28 20:12:27767 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42768 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25769
770 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42771 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25772
[email protected]1c773ea12009-04-28 19:58:42773 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25774 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25775}
776
777// What do various browsers do when the server closes a non-keepalive
778// connection without sending any response header or body?
779//
780// IE7: error page
781// Safari 3.1.2 (Windows): error page
782// Firefox 3.0.1: blank page
783// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42784// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
785// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25786TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
787 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42788 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35789 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
790 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42791 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25792 };
[email protected]31a2bfe2010-02-09 08:03:39793 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
794 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42795 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25796}
[email protected]038e9a32008-10-08 22:40:16797
[email protected]fc31d6a42010-06-24 18:05:13798// Test that we correctly reuse a keep-alive connection after receiving a 304.
799TEST_F(HttpNetworkTransactionTest, KeepAliveAfter304) {
800 SessionDependencies session_deps;
801 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
802
803 HttpRequestInfo request;
804 request.method = "GET";
805 request.url = GURL("http://www.foo.com/");
806 request.load_flags = 0;
807
808 MockRead data1_reads[] = {
809 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
810 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
811 MockRead("hello"),
812 };
813 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
814 session_deps.socket_factory.AddSocketDataProvider(&data1);
815
816 MockRead data2_reads[] = {
817 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
818 };
819 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
820 session_deps.socket_factory.AddSocketDataProvider(&data2);
821
822 for (int i = 0; i < 2; ++i) {
823 TestCompletionCallback callback;
824
825 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
826
827 int rv = trans->Start(&request, &callback, BoundNetLog());
828 EXPECT_EQ(ERR_IO_PENDING, rv);
829
830 rv = callback.WaitForResult();
831 EXPECT_EQ(OK, rv);
832
833 const HttpResponseInfo* response = trans->GetResponseInfo();
834 EXPECT_TRUE(response != NULL);
835
836 EXPECT_TRUE(response->headers != NULL);
837 if (i == 0) {
838 EXPECT_EQ("HTTP/1.1 304 Not Modified",
839 response->headers->GetStatusLine());
840 // We intentionally don't read the response in this case, to reflect how
841 // HttpCache::Transaction uses HttpNetworkTransaction.
842 } else {
843 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
844 std::string response_data;
845 rv = ReadTransaction(trans.get(), &response_data);
846 EXPECT_EQ(OK, rv);
847 EXPECT_EQ("hello", response_data);
848 }
849 }
850}
851
[email protected]038e9a32008-10-08 22:40:16852// Test the request-challenge-retry sequence for basic auth.
853// (basic auth is the easiest to mock, because it has no randomness).
854TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59855 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40856 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43857 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16858
[email protected]1c773ea12009-04-28 19:58:42859 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16860 request.method = "GET";
861 request.url = GURL("http://www.google.com/");
862 request.load_flags = 0;
863
[email protected]f9ee6b52008-11-08 06:46:23864 MockWrite data_writes1[] = {
865 MockWrite("GET / HTTP/1.1\r\n"
866 "Host: www.google.com\r\n"
867 "Connection: keep-alive\r\n\r\n"),
868 };
869
[email protected]038e9a32008-10-08 22:40:16870 MockRead data_reads1[] = {
871 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
872 // Give a couple authenticate options (only the middle one is actually
873 // supported).
[email protected]22927ad2009-09-21 19:56:19874 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16875 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
876 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
877 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
878 // Large content-length -- won't matter, as connection will be reset.
879 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42880 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16881 };
882
883 // After calling trans->RestartWithAuth(), this is the request we should
884 // be issuing -- the final header line contains the credentials.
885 MockWrite data_writes2[] = {
886 MockWrite("GET / HTTP/1.1\r\n"
887 "Host: www.google.com\r\n"
888 "Connection: keep-alive\r\n"
889 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
890 };
891
892 // Lastly, the server responds with the actual content.
893 MockRead data_reads2[] = {
894 MockRead("HTTP/1.0 200 OK\r\n"),
895 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
896 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42897 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16898 };
899
[email protected]31a2bfe2010-02-09 08:03:39900 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
901 data_writes1, arraysize(data_writes1));
902 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
903 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59904 session_deps.socket_factory.AddSocketDataProvider(&data1);
905 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16906
907 TestCompletionCallback callback1;
908
[email protected]5a1d7ca2010-04-28 20:12:27909 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42910 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16911
912 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42913 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16914
[email protected]1c773ea12009-04-28 19:58:42915 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16916 EXPECT_FALSE(response == NULL);
917
918 // The password prompt info should have been set in response->auth_challenge.
919 EXPECT_FALSE(response->auth_challenge.get() == NULL);
920
[email protected]71e4573a2009-05-21 22:03:00921 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16922 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
923 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
924
925 TestCompletionCallback callback2;
926
927 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42928 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16929
930 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42931 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16932
933 response = trans->GetResponseInfo();
934 EXPECT_FALSE(response == NULL);
935 EXPECT_TRUE(response->auth_challenge.get() == NULL);
936 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16937}
938
[email protected]861fcd52009-08-26 02:33:46939TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
940 SessionDependencies session_deps;
941 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43942 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46943
944 HttpRequestInfo request;
945 request.method = "GET";
946 request.url = GURL("http://www.google.com/");
947 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
948
949 MockWrite data_writes[] = {
950 MockWrite("GET / HTTP/1.1\r\n"
951 "Host: www.google.com\r\n"
952 "Connection: keep-alive\r\n\r\n"),
953 };
954
955 MockRead data_reads[] = {
956 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
957 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
958 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
959 // Large content-length -- won't matter, as connection will be reset.
960 MockRead("Content-Length: 10000\r\n\r\n"),
961 MockRead(false, ERR_FAILED),
962 };
963
[email protected]31a2bfe2010-02-09 08:03:39964 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
965 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59966 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46967 TestCompletionCallback callback;
968
[email protected]5a1d7ca2010-04-28 20:12:27969 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:46970 EXPECT_EQ(ERR_IO_PENDING, rv);
971
972 rv = callback.WaitForResult();
973 EXPECT_EQ(0, rv);
974
975 const HttpResponseInfo* response = trans->GetResponseInfo();
976 ASSERT_FALSE(response == NULL);
977 EXPECT_TRUE(response->auth_challenge.get() == NULL);
978}
979
[email protected]2d2697f92009-02-18 21:00:32980// Test the request-challenge-retry sequence for basic auth, over a keep-alive
981// connection.
982TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59983 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40984 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43985 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32986
[email protected]1c773ea12009-04-28 19:58:42987 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32988 request.method = "GET";
989 request.url = GURL("http://www.google.com/");
990 request.load_flags = 0;
991
992 MockWrite data_writes1[] = {
993 MockWrite("GET / HTTP/1.1\r\n"
994 "Host: www.google.com\r\n"
995 "Connection: keep-alive\r\n\r\n"),
996
997 // After calling trans->RestartWithAuth(), this is the request we should
998 // be issuing -- the final header line contains the credentials.
999 MockWrite("GET / HTTP/1.1\r\n"
1000 "Host: www.google.com\r\n"
1001 "Connection: keep-alive\r\n"
1002 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1003 };
1004
1005 MockRead data_reads1[] = {
1006 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1007 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1008 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1009 MockRead("Content-Length: 14\r\n\r\n"),
1010 MockRead("Unauthorized\r\n"),
1011
1012 // Lastly, the server responds with the actual content.
1013 MockRead("HTTP/1.1 200 OK\r\n"),
1014 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1015 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421016 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321017 };
1018
[email protected]31a2bfe2010-02-09 08:03:391019 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1020 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591021 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321022
1023 TestCompletionCallback callback1;
1024
[email protected]5a1d7ca2010-04-28 20:12:271025 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421026 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321027
1028 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421029 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321030
[email protected]1c773ea12009-04-28 19:58:421031 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321032 EXPECT_FALSE(response == NULL);
1033
1034 // The password prompt info should have been set in response->auth_challenge.
1035 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1036
[email protected]71e4573a2009-05-21 22:03:001037 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321038 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1039 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1040
1041 TestCompletionCallback callback2;
1042
1043 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421044 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321045
1046 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421047 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321048
1049 response = trans->GetResponseInfo();
1050 EXPECT_FALSE(response == NULL);
1051 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1052 EXPECT_EQ(100, response->headers->GetContentLength());
1053}
1054
1055// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1056// connection and with no response body to drain.
1057TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591058 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401059 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431060 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321061
[email protected]1c773ea12009-04-28 19:58:421062 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321063 request.method = "GET";
1064 request.url = GURL("http://www.google.com/");
1065 request.load_flags = 0;
1066
1067 MockWrite data_writes1[] = {
1068 MockWrite("GET / HTTP/1.1\r\n"
1069 "Host: www.google.com\r\n"
1070 "Connection: keep-alive\r\n\r\n"),
1071
1072 // After calling trans->RestartWithAuth(), this is the request we should
1073 // be issuing -- the final header line contains the credentials.
1074 MockWrite("GET / HTTP/1.1\r\n"
1075 "Host: www.google.com\r\n"
1076 "Connection: keep-alive\r\n"
1077 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1078 };
1079
[email protected]2d2697f92009-02-18 21:00:321080 MockRead data_reads1[] = {
1081 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1082 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311083 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321084
1085 // Lastly, the server responds with the actual content.
1086 MockRead("HTTP/1.1 200 OK\r\n"),
1087 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1088 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421089 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321090 };
1091
[email protected]31a2bfe2010-02-09 08:03:391092 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1093 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591094 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321095
1096 TestCompletionCallback callback1;
1097
[email protected]5a1d7ca2010-04-28 20:12:271098 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421099 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321100
1101 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421102 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321103
[email protected]1c773ea12009-04-28 19:58:421104 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321105 EXPECT_FALSE(response == NULL);
1106
1107 // The password prompt info should have been set in response->auth_challenge.
1108 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1109
[email protected]71e4573a2009-05-21 22:03:001110 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321111 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1112 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1113
1114 TestCompletionCallback callback2;
1115
1116 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421117 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321118
1119 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421120 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321121
1122 response = trans->GetResponseInfo();
1123 EXPECT_FALSE(response == NULL);
1124 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1125 EXPECT_EQ(100, response->headers->GetContentLength());
1126}
1127
1128// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1129// connection and with a large response body to drain.
1130TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591131 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401132 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431133 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321134
[email protected]1c773ea12009-04-28 19:58:421135 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321136 request.method = "GET";
1137 request.url = GURL("http://www.google.com/");
1138 request.load_flags = 0;
1139
1140 MockWrite data_writes1[] = {
1141 MockWrite("GET / HTTP/1.1\r\n"
1142 "Host: www.google.com\r\n"
1143 "Connection: keep-alive\r\n\r\n"),
1144
1145 // After calling trans->RestartWithAuth(), this is the request we should
1146 // be issuing -- the final header line contains the credentials.
1147 MockWrite("GET / HTTP/1.1\r\n"
1148 "Host: www.google.com\r\n"
1149 "Connection: keep-alive\r\n"
1150 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1151 };
1152
1153 // Respond with 5 kb of response body.
1154 std::string large_body_string("Unauthorized");
1155 large_body_string.append(5 * 1024, ' ');
1156 large_body_string.append("\r\n");
1157
1158 MockRead data_reads1[] = {
1159 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1160 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1161 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1162 // 5134 = 12 + 5 * 1024 + 2
1163 MockRead("Content-Length: 5134\r\n\r\n"),
1164 MockRead(true, large_body_string.data(), large_body_string.size()),
1165
1166 // Lastly, the server responds with the actual content.
1167 MockRead("HTTP/1.1 200 OK\r\n"),
1168 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1169 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421170 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321171 };
1172
[email protected]31a2bfe2010-02-09 08:03:391173 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1174 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591175 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321176
1177 TestCompletionCallback callback1;
1178
[email protected]5a1d7ca2010-04-28 20:12:271179 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421180 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321181
1182 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421183 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321184
[email protected]1c773ea12009-04-28 19:58:421185 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321186 EXPECT_FALSE(response == NULL);
1187
1188 // The password prompt info should have been set in response->auth_challenge.
1189 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1190
[email protected]71e4573a2009-05-21 22:03:001191 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321192 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1193 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1194
1195 TestCompletionCallback callback2;
1196
1197 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421198 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321199
1200 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421201 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321202
1203 response = trans->GetResponseInfo();
1204 EXPECT_FALSE(response == NULL);
1205 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1206 EXPECT_EQ(100, response->headers->GetContentLength());
1207}
1208
1209// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311210// connection, but the server gets impatient and closes the connection.
1211TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1212 SessionDependencies session_deps;
1213 scoped_ptr<HttpTransaction> trans(
1214 new HttpNetworkTransaction(CreateSession(&session_deps)));
1215
1216 HttpRequestInfo request;
1217 request.method = "GET";
1218 request.url = GURL("http://www.google.com/");
1219 request.load_flags = 0;
1220
1221 MockWrite data_writes1[] = {
1222 MockWrite("GET / HTTP/1.1\r\n"
1223 "Host: www.google.com\r\n"
1224 "Connection: keep-alive\r\n\r\n"),
1225 // This simulates the seemingly successful write to a closed connection
1226 // if the bug is not fixed.
1227 MockWrite("GET / HTTP/1.1\r\n"
1228 "Host: www.google.com\r\n"
1229 "Connection: keep-alive\r\n"
1230 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1231 };
1232
1233 MockRead data_reads1[] = {
1234 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1235 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1236 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1237 MockRead("Content-Length: 14\r\n\r\n"),
1238 // Tell MockTCPClientSocket to simulate the server closing the connection.
1239 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1240 MockRead("Unauthorized\r\n"),
1241 MockRead(false, OK), // The server closes the connection.
1242 };
1243
1244 // After calling trans->RestartWithAuth(), this is the request we should
1245 // be issuing -- the final header line contains the credentials.
1246 MockWrite data_writes2[] = {
1247 MockWrite("GET / HTTP/1.1\r\n"
1248 "Host: www.google.com\r\n"
1249 "Connection: keep-alive\r\n"
1250 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1251 };
1252
1253 // Lastly, the server responds with the actual content.
1254 MockRead data_reads2[] = {
1255 MockRead("HTTP/1.1 200 OK\r\n"),
1256 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1257 MockRead("Content-Length: 100\r\n\r\n"),
1258 MockRead(false, OK),
1259 };
1260
[email protected]31a2bfe2010-02-09 08:03:391261 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1262 data_writes1, arraysize(data_writes1));
1263 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1264 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311265 session_deps.socket_factory.AddSocketDataProvider(&data1);
1266 session_deps.socket_factory.AddSocketDataProvider(&data2);
1267
1268 TestCompletionCallback callback1;
1269
[email protected]5a1d7ca2010-04-28 20:12:271270 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311271 EXPECT_EQ(ERR_IO_PENDING, rv);
1272
1273 rv = callback1.WaitForResult();
1274 EXPECT_EQ(OK, rv);
1275
1276 const HttpResponseInfo* response = trans->GetResponseInfo();
1277 EXPECT_FALSE(response == NULL);
1278
1279 // The password prompt info should have been set in response->auth_challenge.
1280 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1281
1282 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1283 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1284 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1285
1286 TestCompletionCallback callback2;
1287
1288 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1289 EXPECT_EQ(ERR_IO_PENDING, rv);
1290
1291 rv = callback2.WaitForResult();
1292 EXPECT_EQ(OK, rv);
1293
1294 response = trans->GetResponseInfo();
1295 ASSERT_FALSE(response == NULL);
1296 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1297 EXPECT_EQ(100, response->headers->GetContentLength());
1298}
1299
1300// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321301// proxy connection, when setting up an SSL tunnel.
1302TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1303 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591304 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541305 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1306 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591307 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321308
[email protected]5695b8c2009-09-30 21:36:431309 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321310
[email protected]1c773ea12009-04-28 19:58:421311 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321312 request.method = "GET";
1313 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461314 // Ensure that proxy authentication is attempted even
1315 // when the no authentication data flag is set.
1316 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321317
1318 // Since we have proxy, should try to establish tunnel.
1319 MockWrite data_writes1[] = {
1320 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451321 "Host: www.google.com\r\n"
1322 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321323
1324 // After calling trans->RestartWithAuth(), this is the request we should
1325 // be issuing -- the final header line contains the credentials.
1326 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1327 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451328 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321329 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1330 };
1331
1332 // The proxy responds to the connect with a 407, using a persistent
1333 // connection.
1334 MockRead data_reads1[] = {
1335 // No credentials.
1336 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1337 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1338 MockRead("Content-Length: 10\r\n\r\n"),
1339 MockRead("0123456789"),
1340
1341 // Wrong credentials (wrong password).
1342 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1343 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1344 MockRead("Content-Length: 10\r\n\r\n"),
1345 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421346 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321347 };
1348
[email protected]31a2bfe2010-02-09 08:03:391349 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1350 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591351 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321352
1353 TestCompletionCallback callback1;
1354
[email protected]dbb83db2010-05-11 18:13:391355 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421356 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321357
1358 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421359 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391360 size_t pos = ExpectLogContainsSomewhere(
1361 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1362 NetLog::PHASE_NONE);
1363 ExpectLogContainsSomewhere(
1364 log.entries(), pos,
1365 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1366 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321367
[email protected]1c773ea12009-04-28 19:58:421368 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321369 EXPECT_FALSE(response == NULL);
1370
1371 EXPECT_TRUE(response->headers->IsKeepAlive());
1372 EXPECT_EQ(407, response->headers->response_code());
1373 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421374 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321375
1376 // The password prompt info should have been set in response->auth_challenge.
1377 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1378
[email protected]71e4573a2009-05-21 22:03:001379 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321380 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1381 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1382
1383 TestCompletionCallback callback2;
1384
1385 // Wrong password (should be "bar").
1386 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421387 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321388
1389 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421390 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321391
1392 response = trans->GetResponseInfo();
1393 EXPECT_FALSE(response == NULL);
1394
1395 EXPECT_TRUE(response->headers->IsKeepAlive());
1396 EXPECT_EQ(407, response->headers->response_code());
1397 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421398 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321399
1400 // The password prompt info should have been set in response->auth_challenge.
1401 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1402
[email protected]71e4573a2009-05-21 22:03:001403 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321404 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1405 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131406
1407 // Cleanup the transaction so that the sockets are destroyed before the
1408 // net log goes out of scope.
1409 trans.reset();
1410
1411 // We also need to run the message queue for the socket releases to complete.
1412 MessageLoop::current()->RunAllPending();
[email protected]2d2697f92009-02-18 21:00:321413}
1414
[email protected]a8e9b162009-03-12 00:06:441415// Test that we don't read the response body when we fail to establish a tunnel,
1416// even if the user cancels the proxy's auth attempt.
1417TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1418 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591419 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441420
[email protected]e44de5d2009-06-05 20:12:451421 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441422
[email protected]5695b8c2009-09-30 21:36:431423 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441424
[email protected]1c773ea12009-04-28 19:58:421425 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441426 request.method = "GET";
1427 request.url = GURL("https://www.google.com/");
1428 request.load_flags = 0;
1429
1430 // Since we have proxy, should try to establish tunnel.
1431 MockWrite data_writes[] = {
1432 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451433 "Host: www.google.com\r\n"
1434 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441435 };
1436
1437 // The proxy responds to the connect with a 407.
1438 MockRead data_reads[] = {
1439 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1440 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1441 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421442 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441443 };
1444
[email protected]31a2bfe2010-02-09 08:03:391445 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1446 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591447 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441448
1449 TestCompletionCallback callback;
1450
[email protected]5a1d7ca2010-04-28 20:12:271451 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421452 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441453
1454 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421455 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441456
[email protected]1c773ea12009-04-28 19:58:421457 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441458 EXPECT_FALSE(response == NULL);
1459
1460 EXPECT_TRUE(response->headers->IsKeepAlive());
1461 EXPECT_EQ(407, response->headers->response_code());
1462 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421463 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441464
1465 std::string response_data;
1466 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421467 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441468}
1469
[email protected]8fdbcd22010-05-05 02:54:521470// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1471// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1472TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1473 // We are using a DIRECT connection (i.e. no proxy) for this session.
1474 SessionDependencies session_deps;
1475 scoped_ptr<HttpTransaction> trans(
1476 new HttpNetworkTransaction(CreateSession(&session_deps)));
1477
1478 HttpRequestInfo request;
1479 request.method = "GET";
1480 request.url = GURL("http://www.google.com/");
1481 request.load_flags = 0;
1482
1483 MockWrite data_writes1[] = {
1484 MockWrite("GET / HTTP/1.1\r\n"
1485 "Host: www.google.com\r\n"
1486 "Connection: keep-alive\r\n\r\n"),
1487 };
1488
1489 MockRead data_reads1[] = {
1490 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1491 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1492 // Large content-length -- won't matter, as connection will be reset.
1493 MockRead("Content-Length: 10000\r\n\r\n"),
1494 MockRead(false, ERR_FAILED),
1495 };
1496
1497 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1498 data_writes1, arraysize(data_writes1));
1499 session_deps.socket_factory.AddSocketDataProvider(&data1);
1500
1501 TestCompletionCallback callback;
1502
1503 int rv = trans->Start(&request, &callback, BoundNetLog());
1504 EXPECT_EQ(ERR_IO_PENDING, rv);
1505
1506 rv = callback.WaitForResult();
1507 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1508}
1509
[email protected]ff007e162009-05-23 09:13:151510void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081511 const MockRead& status, int expected_status) {
1512 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591513 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081514
[email protected]228ff742009-06-05 01:19:591515 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081516
[email protected]5695b8c2009-09-30 21:36:431517 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081518
[email protected]1c773ea12009-04-28 19:58:421519 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081520 request.method = "GET";
1521 request.url = GURL("https://www.google.com/");
1522 request.load_flags = 0;
1523
1524 // Since we have proxy, should try to establish tunnel.
1525 MockWrite data_writes[] = {
1526 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451527 "Host: www.google.com\r\n"
1528 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081529 };
1530
1531 MockRead data_reads[] = {
1532 status,
1533 MockRead("Content-Length: 10\r\n\r\n"),
1534 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421535 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081536 };
1537
[email protected]31a2bfe2010-02-09 08:03:391538 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1539 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591540 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081541
1542 TestCompletionCallback callback;
1543
[email protected]5a1d7ca2010-04-28 20:12:271544 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421545 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081546
1547 rv = callback.WaitForResult();
1548 EXPECT_EQ(expected_status, rv);
1549}
1550
[email protected]ff007e162009-05-23 09:13:151551void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081552 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421553 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081554}
1555
1556TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1557 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1558}
1559
1560TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1561 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1562}
1563
1564TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1565 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1566}
1567
1568TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1569 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1570}
1571
1572TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1573 ConnectStatusHelper(
1574 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1575}
1576
1577TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1578 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1579}
1580
1581TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1582 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1583}
1584
1585TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1586 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1587}
1588
1589TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1590 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1591}
1592
1593TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1594 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1595}
1596
1597TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1598 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1599}
1600
1601TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1602 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1603}
1604
1605TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1606 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1607}
1608
1609TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1610 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1611}
1612
1613TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1614 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1615}
1616
1617TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1618 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1619}
1620
1621TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1622 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1623}
1624
1625TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1626 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1627}
1628
1629TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1630 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1631}
1632
1633TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1634 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1635}
1636
1637TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1638 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1639}
1640
1641TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1642 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1643}
1644
1645TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1646 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1647}
1648
1649TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1650 ConnectStatusHelperWithExpectedStatus(
1651 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:541652 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:081653}
1654
1655TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1656 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1657}
1658
1659TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1660 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1661}
1662
1663TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1664 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1665}
1666
1667TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1668 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1669}
1670
1671TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1672 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1673}
1674
1675TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1676 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1677}
1678
1679TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1680 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1681}
1682
1683TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1684 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1685}
1686
1687TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1688 ConnectStatusHelper(
1689 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1690}
1691
1692TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1693 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1694}
1695
1696TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1697 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1698}
1699
1700TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1701 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1702}
1703
1704TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1705 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1706}
1707
1708TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1709 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1710}
1711
1712TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1713 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1714}
1715
1716TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1717 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1718}
1719
[email protected]038e9a32008-10-08 22:40:161720// Test the flow when both the proxy server AND origin server require
1721// authentication. Again, this uses basic auth for both since that is
1722// the simplest to mock.
1723TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591724 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011725
[email protected]038e9a32008-10-08 22:40:161726 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421727 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431728 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161729
[email protected]1c773ea12009-04-28 19:58:421730 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161731 request.method = "GET";
1732 request.url = GURL("http://www.google.com/");
1733 request.load_flags = 0;
1734
[email protected]f9ee6b52008-11-08 06:46:231735 MockWrite data_writes1[] = {
1736 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1737 "Host: www.google.com\r\n"
1738 "Proxy-Connection: keep-alive\r\n\r\n"),
1739 };
1740
[email protected]038e9a32008-10-08 22:40:161741 MockRead data_reads1[] = {
1742 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1743 // Give a couple authenticate options (only the middle one is actually
1744 // supported).
[email protected]22927ad2009-09-21 19:56:191745 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161746 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1747 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1748 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1749 // Large content-length -- won't matter, as connection will be reset.
1750 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421751 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161752 };
1753
1754 // After calling trans->RestartWithAuth() the first time, this is the
1755 // request we should be issuing -- the final header line contains the
1756 // proxy's credentials.
1757 MockWrite data_writes2[] = {
1758 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1759 "Host: www.google.com\r\n"
1760 "Proxy-Connection: keep-alive\r\n"
1761 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1762 };
1763
1764 // Now the proxy server lets the request pass through to origin server.
1765 // The origin server responds with a 401.
1766 MockRead data_reads2[] = {
1767 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1768 // Note: We are using the same realm-name as the proxy server. This is
1769 // completely valid, as realms are unique across hosts.
1770 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1771 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1772 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421773 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161774 };
1775
1776 // After calling trans->RestartWithAuth() the second time, we should send
1777 // the credentials for both the proxy and origin server.
1778 MockWrite data_writes3[] = {
1779 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1780 "Host: www.google.com\r\n"
1781 "Proxy-Connection: keep-alive\r\n"
1782 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1783 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1784 };
1785
1786 // Lastly we get the desired content.
1787 MockRead data_reads3[] = {
1788 MockRead("HTTP/1.0 200 OK\r\n"),
1789 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1790 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421791 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161792 };
1793
[email protected]31a2bfe2010-02-09 08:03:391794 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1795 data_writes1, arraysize(data_writes1));
1796 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1797 data_writes2, arraysize(data_writes2));
1798 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1799 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591800 session_deps.socket_factory.AddSocketDataProvider(&data1);
1801 session_deps.socket_factory.AddSocketDataProvider(&data2);
1802 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161803
1804 TestCompletionCallback callback1;
1805
[email protected]5a1d7ca2010-04-28 20:12:271806 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421807 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161808
1809 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421810 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161811
[email protected]1c773ea12009-04-28 19:58:421812 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161813 EXPECT_FALSE(response == NULL);
1814
1815 // The password prompt info should have been set in response->auth_challenge.
1816 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1817
[email protected]71e4573a2009-05-21 22:03:001818 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161819 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1820 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1821
1822 TestCompletionCallback callback2;
1823
1824 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421825 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161826
1827 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421828 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161829
1830 response = trans->GetResponseInfo();
1831 EXPECT_FALSE(response == NULL);
1832 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1833
[email protected]71e4573a2009-05-21 22:03:001834 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161835 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1836 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1837
1838 TestCompletionCallback callback3;
1839
1840 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421841 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161842
1843 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421844 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161845
1846 response = trans->GetResponseInfo();
1847 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1848 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161849}
[email protected]4ddaf2502008-10-23 18:26:191850
[email protected]ea9dc9a2009-09-05 00:43:321851// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1852// can't hook into its internals to cause it to generate predictable NTLM
1853// authorization headers.
1854#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291855// The NTLM authentication unit tests were generated by capturing the HTTP
1856// requests and responses using Fiddler 2 and inspecting the generated random
1857// bytes in the debugger.
1858
1859// Enter the correct password and authenticate successfully.
1860TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421861 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:111862 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591863 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401864 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431865 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241866
[email protected]1c773ea12009-04-28 19:58:421867 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241868 request.method = "GET";
1869 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1870 request.load_flags = 0;
1871
1872 MockWrite data_writes1[] = {
1873 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1874 "Host: 172.22.68.17\r\n"
1875 "Connection: keep-alive\r\n\r\n"),
1876 };
1877
1878 MockRead data_reads1[] = {
1879 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:041880 // Negotiate and NTLM are often requested together. However, we only want
1881 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
1882 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:241883 MockRead("WWW-Authenticate: NTLM\r\n"),
1884 MockRead("Connection: close\r\n"),
1885 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361886 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241887 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421888 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241889 };
1890
1891 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221892 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241893 // request we should be issuing -- the final header line contains a Type
1894 // 1 message.
1895 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1896 "Host: 172.22.68.17\r\n"
1897 "Connection: keep-alive\r\n"
1898 "Authorization: NTLM "
1899 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1900
1901 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1902 // (the credentials for the origin server). The second request continues
1903 // on the same connection.
1904 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1905 "Host: 172.22.68.17\r\n"
1906 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291907 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1908 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1909 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1910 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1911 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241912 };
1913
1914 MockRead data_reads2[] = {
1915 // The origin server responds with a Type 2 message.
1916 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1917 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291918 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241919 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1920 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1921 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1922 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1923 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1924 "BtAAAAAAA=\r\n"),
1925 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361926 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241927 MockRead("You are not authorized to view this page\r\n"),
1928
1929 // Lastly we get the desired content.
1930 MockRead("HTTP/1.1 200 OK\r\n"),
1931 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1932 MockRead("Content-Length: 13\r\n\r\n"),
1933 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421934 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241935 };
1936
[email protected]31a2bfe2010-02-09 08:03:391937 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1938 data_writes1, arraysize(data_writes1));
1939 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1940 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591941 session_deps.socket_factory.AddSocketDataProvider(&data1);
1942 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241943
1944 TestCompletionCallback callback1;
1945
[email protected]5a1d7ca2010-04-28 20:12:271946 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421947 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241948
1949 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421950 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241951
[email protected]0757e7702009-03-27 04:00:221952 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1953 TestCompletionCallback callback2;
1954 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421955 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221956 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421957 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221958 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1959
[email protected]1c773ea12009-04-28 19:58:421960 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:041961 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:241962
[email protected]aef04272010-06-28 18:03:041963 // The password prompt info should have been set in
1964 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:241965 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1966
[email protected]71e4573a2009-05-21 22:03:001967 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241968 EXPECT_EQ(L"", response->auth_challenge->realm);
1969 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1970
[email protected]0757e7702009-03-27 04:00:221971 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241972
[email protected]0757e7702009-03-27 04:00:221973 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421974 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241975
[email protected]0757e7702009-03-27 04:00:221976 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421977 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241978
1979 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:041980 ASSERT_FALSE(response == NULL);
1981
[email protected]3f918782009-02-28 01:29:241982 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1983 EXPECT_EQ(13, response->headers->GetContentLength());
1984}
1985
[email protected]385a4672009-03-11 22:21:291986// Enter a wrong password, and then the correct one.
1987TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421988 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:111989 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591990 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401991 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431992 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291993
[email protected]1c773ea12009-04-28 19:58:421994 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291995 request.method = "GET";
1996 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1997 request.load_flags = 0;
1998
1999 MockWrite data_writes1[] = {
2000 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2001 "Host: 172.22.68.17\r\n"
2002 "Connection: keep-alive\r\n\r\n"),
2003 };
2004
2005 MockRead data_reads1[] = {
2006 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042007 // Negotiate and NTLM are often requested together. However, we only want
2008 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2009 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292010 MockRead("WWW-Authenticate: NTLM\r\n"),
2011 MockRead("Connection: close\r\n"),
2012 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362013 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292014 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422015 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292016 };
2017
2018 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222019 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292020 // request we should be issuing -- the final header line contains a Type
2021 // 1 message.
2022 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2023 "Host: 172.22.68.17\r\n"
2024 "Connection: keep-alive\r\n"
2025 "Authorization: NTLM "
2026 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2027
2028 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2029 // (the credentials for the origin server). The second request continues
2030 // on the same connection.
2031 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2032 "Host: 172.22.68.17\r\n"
2033 "Connection: keep-alive\r\n"
2034 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2035 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2036 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2037 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2038 "4Ww7b7E=\r\n\r\n"),
2039 };
2040
2041 MockRead data_reads2[] = {
2042 // The origin server responds with a Type 2 message.
2043 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2044 MockRead("WWW-Authenticate: NTLM "
2045 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2046 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2047 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2048 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2049 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2050 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2051 "BtAAAAAAA=\r\n"),
2052 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362053 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292054 MockRead("You are not authorized to view this page\r\n"),
2055
2056 // Wrong password.
2057 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292058 MockRead("WWW-Authenticate: NTLM\r\n"),
2059 MockRead("Connection: close\r\n"),
2060 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362061 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292062 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422063 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292064 };
2065
2066 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222067 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292068 // request we should be issuing -- the final header line contains a Type
2069 // 1 message.
2070 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2071 "Host: 172.22.68.17\r\n"
2072 "Connection: keep-alive\r\n"
2073 "Authorization: NTLM "
2074 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2075
2076 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2077 // (the credentials for the origin server). The second request continues
2078 // on the same connection.
2079 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2080 "Host: 172.22.68.17\r\n"
2081 "Connection: keep-alive\r\n"
2082 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2083 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2084 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2085 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2086 "+4MUm7c=\r\n\r\n"),
2087 };
2088
2089 MockRead data_reads3[] = {
2090 // The origin server responds with a Type 2 message.
2091 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2092 MockRead("WWW-Authenticate: NTLM "
2093 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2094 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2095 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2096 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2097 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2098 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2099 "BtAAAAAAA=\r\n"),
2100 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362101 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292102 MockRead("You are not authorized to view this page\r\n"),
2103
2104 // Lastly we get the desired content.
2105 MockRead("HTTP/1.1 200 OK\r\n"),
2106 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2107 MockRead("Content-Length: 13\r\n\r\n"),
2108 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422109 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292110 };
2111
[email protected]31a2bfe2010-02-09 08:03:392112 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2113 data_writes1, arraysize(data_writes1));
2114 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2115 data_writes2, arraysize(data_writes2));
2116 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2117 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592118 session_deps.socket_factory.AddSocketDataProvider(&data1);
2119 session_deps.socket_factory.AddSocketDataProvider(&data2);
2120 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292121
2122 TestCompletionCallback callback1;
2123
[email protected]5a1d7ca2010-04-28 20:12:272124 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422125 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292126
2127 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422128 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292129
[email protected]0757e7702009-03-27 04:00:222130 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292131 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:222132 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422133 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292134 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422135 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222136 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292137
[email protected]1c773ea12009-04-28 19:58:422138 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292139 EXPECT_FALSE(response == NULL);
2140
2141 // The password prompt info should have been set in response->auth_challenge.
2142 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2143
[email protected]71e4573a2009-05-21 22:03:002144 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292145 EXPECT_EQ(L"", response->auth_challenge->realm);
2146 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2147
2148 TestCompletionCallback callback3;
2149
[email protected]0757e7702009-03-27 04:00:222150 // Enter the wrong password.
2151 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:422152 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292153
2154 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422155 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292156
[email protected]0757e7702009-03-27 04:00:222157 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2158 TestCompletionCallback callback4;
2159 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422160 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222161 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422162 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222163 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2164
2165 response = trans->GetResponseInfo();
2166 EXPECT_FALSE(response == NULL);
2167
2168 // The password prompt info should have been set in response->auth_challenge.
2169 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2170
[email protected]71e4573a2009-05-21 22:03:002171 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222172 EXPECT_EQ(L"", response->auth_challenge->realm);
2173 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2174
2175 TestCompletionCallback callback5;
2176
2177 // Now enter the right password.
2178 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422179 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222180
2181 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422182 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222183
[email protected]385a4672009-03-11 22:21:292184 response = trans->GetResponseInfo();
2185 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2186 EXPECT_EQ(13, response->headers->GetContentLength());
2187}
[email protected]ea9dc9a2009-09-05 00:43:322188#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292189
[email protected]4ddaf2502008-10-23 18:26:192190// Test reading a server response which has only headers, and no body.
2191// After some maximum number of bytes is consumed, the transaction should
2192// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2193TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592194 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402195 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432196 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192197
[email protected]1c773ea12009-04-28 19:58:422198 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192199 request.method = "GET";
2200 request.url = GURL("http://www.google.com/");
2201 request.load_flags = 0;
2202
[email protected]b75b7b2f2009-10-06 00:54:532203 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432204 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532205 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192206
2207 MockRead data_reads[] = {
2208 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432209 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192210 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422211 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192212 };
[email protected]31a2bfe2010-02-09 08:03:392213 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592214 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192215
2216 TestCompletionCallback callback;
2217
[email protected]5a1d7ca2010-04-28 20:12:272218 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422219 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192220
2221 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422222 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192223
[email protected]1c773ea12009-04-28 19:58:422224 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192225 EXPECT_TRUE(response == NULL);
2226}
[email protected]f4e426b2008-11-05 00:24:492227
2228// Make sure that we don't try to reuse a TCPClientSocket when failing to
2229// establish tunnel.
2230// http://code.google.com/p/chromium/issues/detail?id=3772
2231TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2232 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592233 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012234
[email protected]228ff742009-06-05 01:19:592235 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492236
[email protected]5695b8c2009-09-30 21:36:432237 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492238
[email protected]1c773ea12009-04-28 19:58:422239 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492240 request.method = "GET";
2241 request.url = GURL("https://www.google.com/");
2242 request.load_flags = 0;
2243
2244 // Since we have proxy, should try to establish tunnel.
2245 MockWrite data_writes1[] = {
2246 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452247 "Host: www.google.com\r\n"
2248 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492249 };
2250
[email protected]77848d12008-11-14 00:00:222251 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492252 // connection. Usually a proxy would return 501 (not implemented),
2253 // or 200 (tunnel established).
2254 MockRead data_reads1[] = {
2255 MockRead("HTTP/1.1 404 Not Found\r\n"),
2256 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422257 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492258 };
2259
[email protected]31a2bfe2010-02-09 08:03:392260 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2261 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592262 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492263
2264 TestCompletionCallback callback1;
2265
[email protected]5a1d7ca2010-04-28 20:12:272266 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422267 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492268
2269 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422270 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492271
[email protected]1c773ea12009-04-28 19:58:422272 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082273 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492274
[email protected]b4404c02009-04-10 16:38:522275 // Empty the current queue. This is necessary because idle sockets are
2276 // added to the connection pool asynchronously with a PostTask.
2277 MessageLoop::current()->RunAllPending();
2278
[email protected]f4e426b2008-11-05 00:24:492279 // We now check to make sure the TCPClientSocket was not added back to
2280 // the pool.
[email protected]a937a06d2009-08-19 21:19:242281 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492282 trans.reset();
[email protected]b4404c02009-04-10 16:38:522283 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492284 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242285 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492286}
[email protected]372d34a2008-11-05 21:30:512287
[email protected]1b157c02009-04-21 01:55:402288// Make sure that we recycle a socket after reading all of the response body.
2289TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592290 SessionDependencies session_deps;
2291 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402292
[email protected]5695b8c2009-09-30 21:36:432293 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402294
[email protected]1c773ea12009-04-28 19:58:422295 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402296 request.method = "GET";
2297 request.url = GURL("http://www.google.com/");
2298 request.load_flags = 0;
2299
2300 MockRead data_reads[] = {
2301 // A part of the response body is received with the response headers.
2302 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2303 // The rest of the response body is received in two parts.
2304 MockRead("lo"),
2305 MockRead(" world"),
2306 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422307 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402308 };
2309
[email protected]31a2bfe2010-02-09 08:03:392310 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592311 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402312
2313 TestCompletionCallback callback;
2314
[email protected]5a1d7ca2010-04-28 20:12:272315 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422316 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402317
2318 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422319 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402320
[email protected]1c773ea12009-04-28 19:58:422321 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402322 EXPECT_TRUE(response != NULL);
2323
2324 EXPECT_TRUE(response->headers != NULL);
2325 std::string status_line = response->headers->GetStatusLine();
2326 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2327
[email protected]a937a06d2009-08-19 21:19:242328 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402329
2330 std::string response_data;
2331 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422332 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402333 EXPECT_EQ("hello world", response_data);
2334
2335 // Empty the current queue. This is necessary because idle sockets are
2336 // added to the connection pool asynchronously with a PostTask.
2337 MessageLoop::current()->RunAllPending();
2338
2339 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242340 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402341}
2342
[email protected]b4404c02009-04-10 16:38:522343// Make sure that we recycle a socket after a zero-length response.
2344// http://crbug.com/9880
2345TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592346 SessionDependencies session_deps;
2347 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522348
[email protected]5695b8c2009-09-30 21:36:432349 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522350
[email protected]1c773ea12009-04-28 19:58:422351 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522352 request.method = "GET";
2353 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2354 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2355 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2356 "rt=prt.2642,ol.2649,xjs.2951");
2357 request.load_flags = 0;
2358
2359 MockRead data_reads[] = {
2360 MockRead("HTTP/1.1 204 No Content\r\n"
2361 "Content-Length: 0\r\n"
2362 "Content-Type: text/html\r\n\r\n"),
2363 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422364 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522365 };
2366
[email protected]31a2bfe2010-02-09 08:03:392367 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592368 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522369
2370 TestCompletionCallback callback;
2371
[email protected]5a1d7ca2010-04-28 20:12:272372 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422373 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522374
2375 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422376 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522377
[email protected]1c773ea12009-04-28 19:58:422378 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522379 EXPECT_TRUE(response != NULL);
2380
2381 EXPECT_TRUE(response->headers != NULL);
2382 std::string status_line = response->headers->GetStatusLine();
2383 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2384
[email protected]a937a06d2009-08-19 21:19:242385 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522386
2387 std::string response_data;
2388 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422389 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522390 EXPECT_EQ("", response_data);
2391
2392 // Empty the current queue. This is necessary because idle sockets are
2393 // added to the connection pool asynchronously with a PostTask.
2394 MessageLoop::current()->RunAllPending();
2395
2396 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242397 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522398}
2399
[email protected]372d34a2008-11-05 21:30:512400TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422401 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512402 // Transaction 1: a GET request that succeeds. The socket is recycled
2403 // after use.
2404 request[0].method = "GET";
2405 request[0].url = GURL("http://www.google.com/");
2406 request[0].load_flags = 0;
2407 // Transaction 2: a POST request. Reuses the socket kept alive from
2408 // transaction 1. The first attempts fails when writing the POST data.
2409 // This causes the transaction to retry with a new socket. The second
2410 // attempt succeeds.
2411 request[1].method = "POST";
2412 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422413 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512414 request[1].upload_data->AppendBytes("foo", 3);
2415 request[1].load_flags = 0;
2416
[email protected]228ff742009-06-05 01:19:592417 SessionDependencies session_deps;
2418 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512419
2420 // The first socket is used for transaction 1 and the first attempt of
2421 // transaction 2.
2422
2423 // The response of transaction 1.
2424 MockRead data_reads1[] = {
2425 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2426 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422427 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512428 };
2429 // The mock write results of transaction 1 and the first attempt of
2430 // transaction 2.
2431 MockWrite data_writes1[] = {
2432 MockWrite(false, 64), // GET
2433 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422434 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512435 };
[email protected]31a2bfe2010-02-09 08:03:392436 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2437 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512438
2439 // The second socket is used for the second attempt of transaction 2.
2440
2441 // The response of transaction 2.
2442 MockRead data_reads2[] = {
2443 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2444 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422445 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512446 };
2447 // The mock write results of the second attempt of transaction 2.
2448 MockWrite data_writes2[] = {
2449 MockWrite(false, 93), // POST
2450 MockWrite(false, 3), // POST data
2451 };
[email protected]31a2bfe2010-02-09 08:03:392452 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2453 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512454
[email protected]5ecc992a42009-11-11 01:41:592455 session_deps.socket_factory.AddSocketDataProvider(&data1);
2456 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512457
2458 const char* kExpectedResponseData[] = {
2459 "hello world", "welcome"
2460 };
2461
2462 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422463 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432464 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512465
2466 TestCompletionCallback callback;
2467
[email protected]5a1d7ca2010-04-28 20:12:272468 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422469 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512470
2471 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422472 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512473
[email protected]1c773ea12009-04-28 19:58:422474 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512475 EXPECT_TRUE(response != NULL);
2476
2477 EXPECT_TRUE(response->headers != NULL);
2478 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2479
2480 std::string response_data;
2481 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422482 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512483 EXPECT_EQ(kExpectedResponseData[i], response_data);
2484 }
2485}
[email protected]f9ee6b52008-11-08 06:46:232486
2487// Test the request-challenge-retry sequence for basic auth when there is
2488// an identity in the URL. The request should be sent as normal, but when
2489// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322490TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592491 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402492 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432493 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232494
[email protected]1c773ea12009-04-28 19:58:422495 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232496 request.method = "GET";
2497 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292498 request.url = GURL("http://foo:b@[email protected]/");
2499
2500 // The password contains an escaped character -- for this test to pass it
2501 // will need to be unescaped by HttpNetworkTransaction.
2502 EXPECT_EQ("b%40r", request.url.password());
2503
[email protected]ea9dc9a2009-09-05 00:43:322504 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232505
2506 MockWrite data_writes1[] = {
2507 MockWrite("GET / HTTP/1.1\r\n"
2508 "Host: www.google.com\r\n"
2509 "Connection: keep-alive\r\n\r\n"),
2510 };
2511
2512 MockRead data_reads1[] = {
2513 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2514 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2515 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422516 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232517 };
2518
2519 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322520 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232521 MockWrite data_writes2[] = {
2522 MockWrite("GET / HTTP/1.1\r\n"
2523 "Host: www.google.com\r\n"
2524 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292525 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232526 };
2527
2528 MockRead data_reads2[] = {
2529 MockRead("HTTP/1.0 200 OK\r\n"),
2530 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422531 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232532 };
2533
[email protected]31a2bfe2010-02-09 08:03:392534 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2535 data_writes1, arraysize(data_writes1));
2536 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2537 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592538 session_deps.socket_factory.AddSocketDataProvider(&data1);
2539 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232540
2541 TestCompletionCallback callback1;
2542
[email protected]5a1d7ca2010-04-28 20:12:272543 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422544 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232545
2546 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422547 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232548
[email protected]0757e7702009-03-27 04:00:222549 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2550 TestCompletionCallback callback2;
2551 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422552 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222553 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422554 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222555 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2556
[email protected]1c773ea12009-04-28 19:58:422557 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232558 EXPECT_FALSE(response == NULL);
2559
2560 // There is no challenge info, since the identity in URL worked.
2561 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2562
2563 EXPECT_EQ(100, response->headers->GetContentLength());
2564
2565 // Empty the current queue.
2566 MessageLoop::current()->RunAllPending();
2567}
2568
[email protected]ea9dc9a2009-09-05 00:43:322569// Test the request-challenge-retry sequence for basic auth when there is
2570// an incorrect identity in the URL. The identity from the URL should be used
2571// only once.
2572TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2573 SessionDependencies session_deps;
2574 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432575 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322576
2577 HttpRequestInfo request;
2578 request.method = "GET";
2579 // Note: the URL has a username:password in it. The password "baz" is
2580 // wrong (should be "bar").
2581 request.url = GURL("http://foo:[email protected]/");
2582
2583 request.load_flags = LOAD_NORMAL;
2584
2585 MockWrite data_writes1[] = {
2586 MockWrite("GET / HTTP/1.1\r\n"
2587 "Host: www.google.com\r\n"
2588 "Connection: keep-alive\r\n\r\n"),
2589 };
2590
2591 MockRead data_reads1[] = {
2592 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2593 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2594 MockRead("Content-Length: 10\r\n\r\n"),
2595 MockRead(false, ERR_FAILED),
2596 };
2597
2598 // After the challenge above, the transaction will be restarted using the
2599 // identity from the url (foo, baz) to answer the challenge.
2600 MockWrite data_writes2[] = {
2601 MockWrite("GET / HTTP/1.1\r\n"
2602 "Host: www.google.com\r\n"
2603 "Connection: keep-alive\r\n"
2604 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2605 };
2606
2607 MockRead data_reads2[] = {
2608 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2609 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2610 MockRead("Content-Length: 10\r\n\r\n"),
2611 MockRead(false, ERR_FAILED),
2612 };
2613
2614 // After the challenge above, the transaction will be restarted using the
2615 // identity supplied by the user (foo, bar) to answer the challenge.
2616 MockWrite data_writes3[] = {
2617 MockWrite("GET / HTTP/1.1\r\n"
2618 "Host: www.google.com\r\n"
2619 "Connection: keep-alive\r\n"
2620 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2621 };
2622
2623 MockRead data_reads3[] = {
2624 MockRead("HTTP/1.0 200 OK\r\n"),
2625 MockRead("Content-Length: 100\r\n\r\n"),
2626 MockRead(false, OK),
2627 };
2628
[email protected]31a2bfe2010-02-09 08:03:392629 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2630 data_writes1, arraysize(data_writes1));
2631 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2632 data_writes2, arraysize(data_writes2));
2633 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2634 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592635 session_deps.socket_factory.AddSocketDataProvider(&data1);
2636 session_deps.socket_factory.AddSocketDataProvider(&data2);
2637 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322638
2639 TestCompletionCallback callback1;
2640
[email protected]5a1d7ca2010-04-28 20:12:272641 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322642 EXPECT_EQ(ERR_IO_PENDING, rv);
2643
2644 rv = callback1.WaitForResult();
2645 EXPECT_EQ(OK, rv);
2646
2647 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2648 TestCompletionCallback callback2;
2649 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2650 EXPECT_EQ(ERR_IO_PENDING, rv);
2651 rv = callback2.WaitForResult();
2652 EXPECT_EQ(OK, rv);
2653 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2654
2655 const HttpResponseInfo* response = trans->GetResponseInfo();
2656 EXPECT_FALSE(response == NULL);
2657 // The password prompt info should have been set in response->auth_challenge.
2658 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2659
2660 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2661 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2662 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2663
2664 TestCompletionCallback callback3;
2665 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2666 EXPECT_EQ(ERR_IO_PENDING, rv);
2667 rv = callback3.WaitForResult();
2668 EXPECT_EQ(OK, rv);
2669 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2670
2671 response = trans->GetResponseInfo();
2672 EXPECT_FALSE(response == NULL);
2673
2674 // There is no challenge info, since the identity worked.
2675 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2676
2677 EXPECT_EQ(100, response->headers->GetContentLength());
2678
2679 // Empty the current queue.
2680 MessageLoop::current()->RunAllPending();
2681}
2682
[email protected]f9ee6b52008-11-08 06:46:232683// Test that previously tried username/passwords for a realm get re-used.
2684TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592685 SessionDependencies session_deps;
2686 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232687
2688 // Transaction 1: authenticate (foo, bar) on MyRealm1
2689 {
[email protected]5695b8c2009-09-30 21:36:432690 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232691
[email protected]1c773ea12009-04-28 19:58:422692 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232693 request.method = "GET";
2694 request.url = GURL("http://www.google.com/x/y/z");
2695 request.load_flags = 0;
2696
2697 MockWrite data_writes1[] = {
2698 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2699 "Host: www.google.com\r\n"
2700 "Connection: keep-alive\r\n\r\n"),
2701 };
2702
2703 MockRead data_reads1[] = {
2704 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2705 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2706 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422707 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232708 };
2709
2710 // Resend with authorization (username=foo, password=bar)
2711 MockWrite data_writes2[] = {
2712 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2713 "Host: www.google.com\r\n"
2714 "Connection: keep-alive\r\n"
2715 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2716 };
2717
2718 // Sever accepts the authorization.
2719 MockRead data_reads2[] = {
2720 MockRead("HTTP/1.0 200 OK\r\n"),
2721 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422722 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232723 };
2724
[email protected]31a2bfe2010-02-09 08:03:392725 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2726 data_writes1, arraysize(data_writes1));
2727 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2728 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592729 session_deps.socket_factory.AddSocketDataProvider(&data1);
2730 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232731
2732 TestCompletionCallback callback1;
2733
[email protected]5a1d7ca2010-04-28 20:12:272734 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422735 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232736
2737 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422738 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232739
[email protected]1c773ea12009-04-28 19:58:422740 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232741 EXPECT_FALSE(response == NULL);
2742
2743 // The password prompt info should have been set in
2744 // response->auth_challenge.
2745 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2746
[email protected]71e4573a2009-05-21 22:03:002747 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232748 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2749 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2750
2751 TestCompletionCallback callback2;
2752
2753 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422754 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232755
2756 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422757 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232758
2759 response = trans->GetResponseInfo();
2760 EXPECT_FALSE(response == NULL);
2761 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2762 EXPECT_EQ(100, response->headers->GetContentLength());
2763 }
2764
2765 // ------------------------------------------------------------------------
2766
2767 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2768 {
[email protected]5695b8c2009-09-30 21:36:432769 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232770
[email protected]1c773ea12009-04-28 19:58:422771 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232772 request.method = "GET";
2773 // Note that Transaction 1 was at /x/y/z, so this is in the same
2774 // protection space as MyRealm1.
2775 request.url = GURL("http://www.google.com/x/y/a/b");
2776 request.load_flags = 0;
2777
2778 MockWrite data_writes1[] = {
2779 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2780 "Host: www.google.com\r\n"
2781 "Connection: keep-alive\r\n"
2782 // Send preemptive authorization for MyRealm1
2783 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2784 };
2785
2786 // The server didn't like the preemptive authorization, and
2787 // challenges us for a different realm (MyRealm2).
2788 MockRead data_reads1[] = {
2789 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2790 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2791 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422792 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232793 };
2794
2795 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2796 MockWrite data_writes2[] = {
2797 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2798 "Host: www.google.com\r\n"
2799 "Connection: keep-alive\r\n"
2800 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2801 };
2802
2803 // Sever accepts the authorization.
2804 MockRead data_reads2[] = {
2805 MockRead("HTTP/1.0 200 OK\r\n"),
2806 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422807 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232808 };
2809
[email protected]31a2bfe2010-02-09 08:03:392810 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2811 data_writes1, arraysize(data_writes1));
2812 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2813 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592814 session_deps.socket_factory.AddSocketDataProvider(&data1);
2815 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232816
2817 TestCompletionCallback callback1;
2818
[email protected]5a1d7ca2010-04-28 20:12:272819 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422820 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232821
2822 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422823 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232824
[email protected]1c773ea12009-04-28 19:58:422825 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232826 EXPECT_FALSE(response == NULL);
2827
2828 // The password prompt info should have been set in
2829 // response->auth_challenge.
2830 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2831
[email protected]71e4573a2009-05-21 22:03:002832 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232833 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2834 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2835
2836 TestCompletionCallback callback2;
2837
2838 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422839 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232840
2841 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422842 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232843
2844 response = trans->GetResponseInfo();
2845 EXPECT_FALSE(response == NULL);
2846 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2847 EXPECT_EQ(100, response->headers->GetContentLength());
2848 }
2849
2850 // ------------------------------------------------------------------------
2851
2852 // Transaction 3: Resend a request in MyRealm's protection space --
2853 // succeed with preemptive authorization.
2854 {
[email protected]5695b8c2009-09-30 21:36:432855 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232856
[email protected]1c773ea12009-04-28 19:58:422857 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232858 request.method = "GET";
2859 request.url = GURL("http://www.google.com/x/y/z2");
2860 request.load_flags = 0;
2861
2862 MockWrite data_writes1[] = {
2863 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2864 "Host: www.google.com\r\n"
2865 "Connection: keep-alive\r\n"
2866 // The authorization for MyRealm1 gets sent preemptively
2867 // (since the url is in the same protection space)
2868 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2869 };
2870
2871 // Sever accepts the preemptive authorization
2872 MockRead data_reads1[] = {
2873 MockRead("HTTP/1.0 200 OK\r\n"),
2874 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422875 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232876 };
2877
[email protected]31a2bfe2010-02-09 08:03:392878 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2879 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592880 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232881
2882 TestCompletionCallback callback1;
2883
[email protected]5a1d7ca2010-04-28 20:12:272884 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422885 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232886
2887 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422888 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232889
[email protected]1c773ea12009-04-28 19:58:422890 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232891 EXPECT_FALSE(response == NULL);
2892
2893 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2894 EXPECT_EQ(100, response->headers->GetContentLength());
2895 }
2896
2897 // ------------------------------------------------------------------------
2898
2899 // Transaction 4: request another URL in MyRealm (however the
2900 // url is not known to belong to the protection space, so no pre-auth).
2901 {
[email protected]5695b8c2009-09-30 21:36:432902 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232903
[email protected]1c773ea12009-04-28 19:58:422904 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232905 request.method = "GET";
2906 request.url = GURL("http://www.google.com/x/1");
2907 request.load_flags = 0;
2908
2909 MockWrite data_writes1[] = {
2910 MockWrite("GET /x/1 HTTP/1.1\r\n"
2911 "Host: www.google.com\r\n"
2912 "Connection: keep-alive\r\n\r\n"),
2913 };
2914
2915 MockRead data_reads1[] = {
2916 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2917 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2918 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422919 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232920 };
2921
2922 // Resend with authorization from MyRealm's cache.
2923 MockWrite data_writes2[] = {
2924 MockWrite("GET /x/1 HTTP/1.1\r\n"
2925 "Host: www.google.com\r\n"
2926 "Connection: keep-alive\r\n"
2927 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2928 };
2929
2930 // Sever accepts the authorization.
2931 MockRead data_reads2[] = {
2932 MockRead("HTTP/1.0 200 OK\r\n"),
2933 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422934 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232935 };
2936
[email protected]31a2bfe2010-02-09 08:03:392937 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2938 data_writes1, arraysize(data_writes1));
2939 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2940 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592941 session_deps.socket_factory.AddSocketDataProvider(&data1);
2942 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232943
2944 TestCompletionCallback callback1;
2945
[email protected]5a1d7ca2010-04-28 20:12:272946 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422947 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232948
2949 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422950 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232951
[email protected]0757e7702009-03-27 04:00:222952 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2953 TestCompletionCallback callback2;
2954 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422955 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222956 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422957 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222958 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2959
[email protected]1c773ea12009-04-28 19:58:422960 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232961 EXPECT_FALSE(response == NULL);
2962 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2963 EXPECT_EQ(100, response->headers->GetContentLength());
2964 }
2965
2966 // ------------------------------------------------------------------------
2967
2968 // Transaction 5: request a URL in MyRealm, but the server rejects the
2969 // cached identity. Should invalidate and re-prompt.
2970 {
[email protected]5695b8c2009-09-30 21:36:432971 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232972
[email protected]1c773ea12009-04-28 19:58:422973 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232974 request.method = "GET";
2975 request.url = GURL("http://www.google.com/p/q/t");
2976 request.load_flags = 0;
2977
2978 MockWrite data_writes1[] = {
2979 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2980 "Host: www.google.com\r\n"
2981 "Connection: keep-alive\r\n\r\n"),
2982 };
2983
2984 MockRead data_reads1[] = {
2985 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2986 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2987 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422988 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232989 };
2990
2991 // Resend with authorization from cache for MyRealm.
2992 MockWrite data_writes2[] = {
2993 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2994 "Host: www.google.com\r\n"
2995 "Connection: keep-alive\r\n"
2996 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2997 };
2998
2999 // Sever rejects the authorization.
3000 MockRead data_reads2[] = {
3001 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3002 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3003 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423004 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233005 };
3006
3007 // At this point we should prompt for new credentials for MyRealm.
3008 // Restart with username=foo3, password=foo4.
3009 MockWrite data_writes3[] = {
3010 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3011 "Host: www.google.com\r\n"
3012 "Connection: keep-alive\r\n"
3013 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3014 };
3015
3016 // Sever accepts the authorization.
3017 MockRead data_reads3[] = {
3018 MockRead("HTTP/1.0 200 OK\r\n"),
3019 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423020 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233021 };
3022
[email protected]31a2bfe2010-02-09 08:03:393023 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3024 data_writes1, arraysize(data_writes1));
3025 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3026 data_writes2, arraysize(data_writes2));
3027 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3028 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593029 session_deps.socket_factory.AddSocketDataProvider(&data1);
3030 session_deps.socket_factory.AddSocketDataProvider(&data2);
3031 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233032
3033 TestCompletionCallback callback1;
3034
[email protected]5a1d7ca2010-04-28 20:12:273035 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423036 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233037
3038 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423039 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233040
[email protected]0757e7702009-03-27 04:00:223041 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3042 TestCompletionCallback callback2;
3043 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423044 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223045 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423046 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223047 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3048
[email protected]1c773ea12009-04-28 19:58:423049 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233050 EXPECT_FALSE(response == NULL);
3051
3052 // The password prompt info should have been set in
3053 // response->auth_challenge.
3054 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3055
[email protected]71e4573a2009-05-21 22:03:003056 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233057 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3058 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3059
[email protected]0757e7702009-03-27 04:00:223060 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233061
[email protected]0757e7702009-03-27 04:00:223062 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:423063 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233064
[email protected]0757e7702009-03-27 04:00:223065 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423066 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233067
3068 response = trans->GetResponseInfo();
3069 EXPECT_FALSE(response == NULL);
3070 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3071 EXPECT_EQ(100, response->headers->GetContentLength());
3072 }
3073}
[email protected]89ceba9a2009-03-21 03:46:063074
[email protected]3c32c5f2010-05-18 15:18:123075// Tests that nonce count increments when multiple auth attempts
3076// are started with the same nonce.
3077TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3078 SessionDependencies session_deps;
3079 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3080 HttpAuthHandlerDigest::SetFixedCnonce(true);
3081
3082 // Transaction 1: authenticate (foo, bar) on MyRealm1
3083 {
3084 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3085
3086 HttpRequestInfo request;
3087 request.method = "GET";
3088 request.url = GURL("http://www.google.com/x/y/z");
3089 request.load_flags = 0;
3090
3091 MockWrite data_writes1[] = {
3092 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3093 "Host: www.google.com\r\n"
3094 "Connection: keep-alive\r\n\r\n"),
3095 };
3096
3097 MockRead data_reads1[] = {
3098 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3099 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3100 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3101 MockRead(false, OK),
3102 };
3103
3104 // Resend with authorization (username=foo, password=bar)
3105 MockWrite data_writes2[] = {
3106 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3107 "Host: www.google.com\r\n"
3108 "Connection: keep-alive\r\n"
3109 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3110 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3111 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3112 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3113 };
3114
3115 // Sever accepts the authorization.
3116 MockRead data_reads2[] = {
3117 MockRead("HTTP/1.0 200 OK\r\n"),
3118 MockRead(false, OK),
3119 };
3120
3121 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3122 data_writes1, arraysize(data_writes1));
3123 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3124 data_writes2, arraysize(data_writes2));
3125 session_deps.socket_factory.AddSocketDataProvider(&data1);
3126 session_deps.socket_factory.AddSocketDataProvider(&data2);
3127
3128 TestCompletionCallback callback1;
3129
3130 int rv = trans->Start(&request, &callback1, BoundNetLog());
3131 EXPECT_EQ(ERR_IO_PENDING, rv);
3132
3133 rv = callback1.WaitForResult();
3134 EXPECT_EQ(OK, rv);
3135
3136 const HttpResponseInfo* response = trans->GetResponseInfo();
3137 ASSERT_FALSE(response == NULL);
3138
3139 // The password prompt info should have been set in
3140 // response->auth_challenge.
3141 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3142
3143 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3144 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3145 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3146
3147 TestCompletionCallback callback2;
3148
3149 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3150 EXPECT_EQ(ERR_IO_PENDING, rv);
3151
3152 rv = callback2.WaitForResult();
3153 EXPECT_EQ(OK, rv);
3154
3155 response = trans->GetResponseInfo();
3156 ASSERT_FALSE(response == NULL);
3157 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3158 }
3159
3160 // ------------------------------------------------------------------------
3161
3162 // Transaction 2: Request another resource in digestive's protection space.
3163 // This will preemptively add an Authorization header which should have an
3164 // "nc" value of 2 (as compared to 1 in the first use.
3165 {
3166 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3167
3168 HttpRequestInfo request;
3169 request.method = "GET";
3170 // Note that Transaction 1 was at /x/y/z, so this is in the same
3171 // protection space as digest.
3172 request.url = GURL("http://www.google.com/x/y/a/b");
3173 request.load_flags = 0;
3174
3175 MockWrite data_writes1[] = {
3176 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3177 "Host: www.google.com\r\n"
3178 "Connection: keep-alive\r\n"
3179 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3180 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3181 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3182 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3183 };
3184
3185 // Sever accepts the authorization.
3186 MockRead data_reads1[] = {
3187 MockRead("HTTP/1.0 200 OK\r\n"),
3188 MockRead("Content-Length: 100\r\n\r\n"),
3189 MockRead(false, OK),
3190 };
3191
3192 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3193 data_writes1, arraysize(data_writes1));
3194 session_deps.socket_factory.AddSocketDataProvider(&data1);
3195
3196 TestCompletionCallback callback1;
3197
3198 int rv = trans->Start(&request, &callback1, BoundNetLog());
3199 EXPECT_EQ(ERR_IO_PENDING, rv);
3200
3201 rv = callback1.WaitForResult();
3202 EXPECT_EQ(OK, rv);
3203
3204 const HttpResponseInfo* response = trans->GetResponseInfo();
3205 ASSERT_FALSE(response == NULL);
3206 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3207 }
3208}
3209
[email protected]89ceba9a2009-03-21 03:46:063210// Test the ResetStateForRestart() private method.
3211TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3212 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593213 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403214 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433215 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063216
3217 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063218 trans->read_buf_ = new IOBuffer(15);
3219 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573220 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063221
3222 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143223 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573224 response->auth_challenge = new AuthChallengeInfo();
3225 response->ssl_info.cert_status = -15;
3226 response->response_time = base::Time::Now();
3227 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063228
3229 { // Setup state for response_.vary_data
3230 HttpRequestInfo request;
3231 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3232 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573233 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433234 request.extra_headers.SetHeader("Foo", "1");
3235 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573236 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063237 }
3238
3239 // Cause the above state to be reset.
3240 trans->ResetStateForRestart();
3241
3242 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073243 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063244 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573245 EXPECT_EQ(0U, trans->request_headers_.size());
3246 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3247 EXPECT_TRUE(response->headers.get() == NULL);
3248 EXPECT_EQ(false, response->was_cached);
3249 EXPECT_EQ(0, response->ssl_info.cert_status);
3250 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063251}
3252
[email protected]bacff652009-03-31 17:50:333253// Test HTTPS connections to a site with a bad certificate
3254TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593255 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403256 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433257 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333258
3259 HttpRequestInfo request;
3260 request.method = "GET";
3261 request.url = GURL("https://www.google.com/");
3262 request.load_flags = 0;
3263
3264 MockWrite data_writes[] = {
3265 MockWrite("GET / HTTP/1.1\r\n"
3266 "Host: www.google.com\r\n"
3267 "Connection: keep-alive\r\n\r\n"),
3268 };
3269
3270 MockRead data_reads[] = {
3271 MockRead("HTTP/1.0 200 OK\r\n"),
3272 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3273 MockRead("Content-Length: 100\r\n\r\n"),
3274 MockRead(false, OK),
3275 };
3276
[email protected]5ecc992a42009-11-11 01:41:593277 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393278 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3279 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593280 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3281 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333282
[email protected]5ecc992a42009-11-11 01:41:593283 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3284 session_deps.socket_factory.AddSocketDataProvider(&data);
3285 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3286 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333287
3288 TestCompletionCallback callback;
3289
[email protected]5a1d7ca2010-04-28 20:12:273290 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333291 EXPECT_EQ(ERR_IO_PENDING, rv);
3292
3293 rv = callback.WaitForResult();
3294 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3295
3296 rv = trans->RestartIgnoringLastError(&callback);
3297 EXPECT_EQ(ERR_IO_PENDING, rv);
3298
3299 rv = callback.WaitForResult();
3300 EXPECT_EQ(OK, rv);
3301
3302 const HttpResponseInfo* response = trans->GetResponseInfo();
3303
3304 EXPECT_FALSE(response == NULL);
3305 EXPECT_EQ(100, response->headers->GetContentLength());
3306}
3307
3308// Test HTTPS connections to a site with a bad certificate, going through a
3309// proxy
3310TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593311 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333312
3313 HttpRequestInfo request;
3314 request.method = "GET";
3315 request.url = GURL("https://www.google.com/");
3316 request.load_flags = 0;
3317
3318 MockWrite proxy_writes[] = {
3319 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453320 "Host: www.google.com\r\n"
3321 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333322 };
3323
3324 MockRead proxy_reads[] = {
3325 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423326 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333327 };
3328
3329 MockWrite data_writes[] = {
3330 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453331 "Host: www.google.com\r\n"
3332 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333333 MockWrite("GET / HTTP/1.1\r\n"
3334 "Host: www.google.com\r\n"
3335 "Connection: keep-alive\r\n\r\n"),
3336 };
3337
3338 MockRead data_reads[] = {
3339 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3340 MockRead("HTTP/1.0 200 OK\r\n"),
3341 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3342 MockRead("Content-Length: 100\r\n\r\n"),
3343 MockRead(false, OK),
3344 };
3345
[email protected]31a2bfe2010-02-09 08:03:393346 StaticSocketDataProvider ssl_bad_certificate(
3347 proxy_reads, arraysize(proxy_reads),
3348 proxy_writes, arraysize(proxy_writes));
3349 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3350 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593351 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3352 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333353
[email protected]5ecc992a42009-11-11 01:41:593354 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3355 session_deps.socket_factory.AddSocketDataProvider(&data);
3356 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3357 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333358
3359 TestCompletionCallback callback;
3360
3361 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593362 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333363
[email protected]d207a5f2009-06-04 05:28:403364 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433365 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333366
[email protected]5a1d7ca2010-04-28 20:12:273367 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333368 EXPECT_EQ(ERR_IO_PENDING, rv);
3369
3370 rv = callback.WaitForResult();
3371 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3372
3373 rv = trans->RestartIgnoringLastError(&callback);
3374 EXPECT_EQ(ERR_IO_PENDING, rv);
3375
3376 rv = callback.WaitForResult();
3377 EXPECT_EQ(OK, rv);
3378
3379 const HttpResponseInfo* response = trans->GetResponseInfo();
3380
3381 EXPECT_FALSE(response == NULL);
3382 EXPECT_EQ(100, response->headers->GetContentLength());
3383 }
3384}
3385
[email protected]1c773ea12009-04-28 19:58:423386TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593387 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403388 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433389 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423390
3391 HttpRequestInfo request;
3392 request.method = "GET";
3393 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433394 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3395 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423396
3397 MockWrite data_writes[] = {
3398 MockWrite("GET / HTTP/1.1\r\n"
3399 "Host: www.google.com\r\n"
3400 "Connection: keep-alive\r\n"
3401 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3402 };
3403
3404 // Lastly, the server responds with the actual content.
3405 MockRead data_reads[] = {
3406 MockRead("HTTP/1.0 200 OK\r\n"),
3407 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3408 MockRead("Content-Length: 100\r\n\r\n"),
3409 MockRead(false, OK),
3410 };
3411
[email protected]31a2bfe2010-02-09 08:03:393412 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3413 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593414 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423415
3416 TestCompletionCallback callback;
3417
[email protected]5a1d7ca2010-04-28 20:12:273418 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423419 EXPECT_EQ(ERR_IO_PENDING, rv);
3420
3421 rv = callback.WaitForResult();
3422 EXPECT_EQ(OK, rv);
3423}
3424
3425TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593426 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403427 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433428 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423429
3430 HttpRequestInfo request;
3431 request.method = "GET";
3432 request.url = GURL("http://www.google.com/");
3433 request.load_flags = 0;
3434 request.referrer = GURL("http://the.previous.site.com/");
3435
3436 MockWrite data_writes[] = {
3437 MockWrite("GET / HTTP/1.1\r\n"
3438 "Host: www.google.com\r\n"
3439 "Connection: keep-alive\r\n"
3440 "Referer: http://the.previous.site.com/\r\n\r\n"),
3441 };
3442
3443 // Lastly, the server responds with the actual content.
3444 MockRead data_reads[] = {
3445 MockRead("HTTP/1.0 200 OK\r\n"),
3446 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3447 MockRead("Content-Length: 100\r\n\r\n"),
3448 MockRead(false, OK),
3449 };
3450
[email protected]31a2bfe2010-02-09 08:03:393451 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3452 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593453 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423454
3455 TestCompletionCallback callback;
3456
[email protected]5a1d7ca2010-04-28 20:12:273457 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423458 EXPECT_EQ(ERR_IO_PENDING, rv);
3459
3460 rv = callback.WaitForResult();
3461 EXPECT_EQ(OK, rv);
3462}
3463
3464TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593465 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403466 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433467 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423468
3469 HttpRequestInfo request;
3470 request.method = "POST";
3471 request.url = GURL("http://www.google.com/");
3472
3473 MockWrite data_writes[] = {
3474 MockWrite("POST / HTTP/1.1\r\n"
3475 "Host: www.google.com\r\n"
3476 "Connection: keep-alive\r\n"
3477 "Content-Length: 0\r\n\r\n"),
3478 };
3479
3480 // Lastly, the server responds with the actual content.
3481 MockRead data_reads[] = {
3482 MockRead("HTTP/1.0 200 OK\r\n"),
3483 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3484 MockRead("Content-Length: 100\r\n\r\n"),
3485 MockRead(false, OK),
3486 };
3487
[email protected]31a2bfe2010-02-09 08:03:393488 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3489 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593490 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423491
3492 TestCompletionCallback callback;
3493
[email protected]5a1d7ca2010-04-28 20:12:273494 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423495 EXPECT_EQ(ERR_IO_PENDING, rv);
3496
3497 rv = callback.WaitForResult();
3498 EXPECT_EQ(OK, rv);
3499}
3500
3501TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593502 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403503 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433504 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423505
3506 HttpRequestInfo request;
3507 request.method = "PUT";
3508 request.url = GURL("http://www.google.com/");
3509
3510 MockWrite data_writes[] = {
3511 MockWrite("PUT / HTTP/1.1\r\n"
3512 "Host: www.google.com\r\n"
3513 "Connection: keep-alive\r\n"
3514 "Content-Length: 0\r\n\r\n"),
3515 };
3516
3517 // Lastly, the server responds with the actual content.
3518 MockRead data_reads[] = {
3519 MockRead("HTTP/1.0 200 OK\r\n"),
3520 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3521 MockRead("Content-Length: 100\r\n\r\n"),
3522 MockRead(false, OK),
3523 };
3524
[email protected]31a2bfe2010-02-09 08:03:393525 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3526 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593527 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423528
3529 TestCompletionCallback callback;
3530
[email protected]5a1d7ca2010-04-28 20:12:273531 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423532 EXPECT_EQ(ERR_IO_PENDING, rv);
3533
3534 rv = callback.WaitForResult();
3535 EXPECT_EQ(OK, rv);
3536}
3537
3538TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593539 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403540 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433541 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423542
3543 HttpRequestInfo request;
3544 request.method = "HEAD";
3545 request.url = GURL("http://www.google.com/");
3546
3547 MockWrite data_writes[] = {
3548 MockWrite("HEAD / HTTP/1.1\r\n"
3549 "Host: www.google.com\r\n"
3550 "Connection: keep-alive\r\n"
3551 "Content-Length: 0\r\n\r\n"),
3552 };
3553
3554 // Lastly, the server responds with the actual content.
3555 MockRead data_reads[] = {
3556 MockRead("HTTP/1.0 200 OK\r\n"),
3557 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3558 MockRead("Content-Length: 100\r\n\r\n"),
3559 MockRead(false, OK),
3560 };
3561
[email protected]31a2bfe2010-02-09 08:03:393562 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3563 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593564 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423565
3566 TestCompletionCallback callback;
3567
[email protected]5a1d7ca2010-04-28 20:12:273568 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423569 EXPECT_EQ(ERR_IO_PENDING, rv);
3570
3571 rv = callback.WaitForResult();
3572 EXPECT_EQ(OK, rv);
3573}
3574
3575TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593576 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403577 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433578 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423579
3580 HttpRequestInfo request;
3581 request.method = "GET";
3582 request.url = GURL("http://www.google.com/");
3583 request.load_flags = LOAD_BYPASS_CACHE;
3584
3585 MockWrite data_writes[] = {
3586 MockWrite("GET / HTTP/1.1\r\n"
3587 "Host: www.google.com\r\n"
3588 "Connection: keep-alive\r\n"
3589 "Pragma: no-cache\r\n"
3590 "Cache-Control: no-cache\r\n\r\n"),
3591 };
3592
3593 // Lastly, the server responds with the actual content.
3594 MockRead data_reads[] = {
3595 MockRead("HTTP/1.0 200 OK\r\n"),
3596 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3597 MockRead("Content-Length: 100\r\n\r\n"),
3598 MockRead(false, OK),
3599 };
3600
[email protected]31a2bfe2010-02-09 08:03:393601 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3602 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593603 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423604
3605 TestCompletionCallback callback;
3606
[email protected]5a1d7ca2010-04-28 20:12:273607 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423608 EXPECT_EQ(ERR_IO_PENDING, rv);
3609
3610 rv = callback.WaitForResult();
3611 EXPECT_EQ(OK, rv);
3612}
3613
3614TEST_F(HttpNetworkTransactionTest,
3615 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593616 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403617 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433618 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423619
3620 HttpRequestInfo request;
3621 request.method = "GET";
3622 request.url = GURL("http://www.google.com/");
3623 request.load_flags = LOAD_VALIDATE_CACHE;
3624
3625 MockWrite data_writes[] = {
3626 MockWrite("GET / HTTP/1.1\r\n"
3627 "Host: www.google.com\r\n"
3628 "Connection: keep-alive\r\n"
3629 "Cache-Control: max-age=0\r\n\r\n"),
3630 };
3631
3632 // Lastly, the server responds with the actual content.
3633 MockRead data_reads[] = {
3634 MockRead("HTTP/1.0 200 OK\r\n"),
3635 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3636 MockRead("Content-Length: 100\r\n\r\n"),
3637 MockRead(false, OK),
3638 };
3639
[email protected]31a2bfe2010-02-09 08:03:393640 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3641 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593642 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423643
3644 TestCompletionCallback callback;
3645
[email protected]5a1d7ca2010-04-28 20:12:273646 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423647 EXPECT_EQ(ERR_IO_PENDING, rv);
3648
3649 rv = callback.WaitForResult();
3650 EXPECT_EQ(OK, rv);
3651}
3652
3653TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593654 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403655 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433656 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423657
3658 HttpRequestInfo request;
3659 request.method = "GET";
3660 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433661 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423662
3663 MockWrite data_writes[] = {
3664 MockWrite("GET / HTTP/1.1\r\n"
3665 "Host: www.google.com\r\n"
3666 "Connection: keep-alive\r\n"
3667 "FooHeader: Bar\r\n\r\n"),
3668 };
3669
3670 // Lastly, the server responds with the actual content.
3671 MockRead data_reads[] = {
3672 MockRead("HTTP/1.0 200 OK\r\n"),
3673 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3674 MockRead("Content-Length: 100\r\n\r\n"),
3675 MockRead(false, OK),
3676 };
3677
[email protected]31a2bfe2010-02-09 08:03:393678 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3679 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593680 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423681
3682 TestCompletionCallback callback;
3683
[email protected]5a1d7ca2010-04-28 20:12:273684 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423685 EXPECT_EQ(ERR_IO_PENDING, rv);
3686
3687 rv = callback.WaitForResult();
3688 EXPECT_EQ(OK, rv);
3689}
3690
[email protected]270c6412010-03-29 22:02:473691TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3692 SessionDependencies session_deps;
3693 scoped_ptr<HttpTransaction> trans(
3694 new HttpNetworkTransaction(CreateSession(&session_deps)));
3695
3696 HttpRequestInfo request;
3697 request.method = "GET";
3698 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433699 request.extra_headers.SetHeader("referer", "www.foo.com");
3700 request.extra_headers.SetHeader("hEllo", "Kitty");
3701 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473702
3703 MockWrite data_writes[] = {
3704 MockWrite("GET / HTTP/1.1\r\n"
3705 "Host: www.google.com\r\n"
3706 "Connection: keep-alive\r\n"
3707 "hEllo: Kitty\r\n"
3708 "FoO: bar\r\n\r\n"),
3709 };
3710
3711 // Lastly, the server responds with the actual content.
3712 MockRead data_reads[] = {
3713 MockRead("HTTP/1.0 200 OK\r\n"),
3714 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3715 MockRead("Content-Length: 100\r\n\r\n"),
3716 MockRead(false, OK),
3717 };
3718
3719 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3720 data_writes, arraysize(data_writes));
3721 session_deps.socket_factory.AddSocketDataProvider(&data);
3722
3723 TestCompletionCallback callback;
3724
[email protected]5a1d7ca2010-04-28 20:12:273725 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473726 EXPECT_EQ(ERR_IO_PENDING, rv);
3727
3728 rv = callback.WaitForResult();
3729 EXPECT_EQ(OK, rv);
3730}
3731
[email protected]3cd17242009-06-23 02:59:023732TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093733 SessionDependencies session_deps(
3734 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023735
3736 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433737 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023738
3739 HttpRequestInfo request;
3740 request.method = "GET";
3741 request.url = GURL("http://www.google.com/");
3742 request.load_flags = 0;
3743
3744 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3745 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3746
3747 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353748 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023749 MockWrite("GET / HTTP/1.1\r\n"
3750 "Host: www.google.com\r\n"
3751 "Connection: keep-alive\r\n\r\n")
3752 };
3753
3754 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593755 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023756 MockRead("HTTP/1.0 200 OK\r\n"),
3757 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3758 MockRead("Payload"),
3759 MockRead(false, OK)
3760 };
3761
[email protected]31a2bfe2010-02-09 08:03:393762 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3763 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593764 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023765
3766 TestCompletionCallback callback;
3767
[email protected]5a1d7ca2010-04-28 20:12:273768 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023769 EXPECT_EQ(ERR_IO_PENDING, rv);
3770
3771 rv = callback.WaitForResult();
3772 EXPECT_EQ(OK, rv);
3773
3774 const HttpResponseInfo* response = trans->GetResponseInfo();
3775 EXPECT_FALSE(response == NULL);
3776
3777 std::string response_text;
3778 rv = ReadTransaction(trans.get(), &response_text);
3779 EXPECT_EQ(OK, rv);
3780 EXPECT_EQ("Payload", response_text);
3781}
3782
3783TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093784 SessionDependencies session_deps(
3785 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023786
3787 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433788 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023789
3790 HttpRequestInfo request;
3791 request.method = "GET";
3792 request.url = GURL("https://www.google.com/");
3793 request.load_flags = 0;
3794
3795 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3796 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3797
3798 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353799 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3800 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023801 MockWrite("GET / HTTP/1.1\r\n"
3802 "Host: www.google.com\r\n"
3803 "Connection: keep-alive\r\n\r\n")
3804 };
3805
3806 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353807 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3808 arraysize(read_buffer)),
3809 MockRead("HTTP/1.0 200 OK\r\n"),
3810 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3811 MockRead("Payload"),
3812 MockRead(false, OK)
3813 };
3814
[email protected]31a2bfe2010-02-09 08:03:393815 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3816 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593817 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353818
[email protected]5ecc992a42009-11-11 01:41:593819 SSLSocketDataProvider ssl(true, OK);
3820 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353821
3822 TestCompletionCallback callback;
3823
[email protected]5a1d7ca2010-04-28 20:12:273824 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353825 EXPECT_EQ(ERR_IO_PENDING, rv);
3826
3827 rv = callback.WaitForResult();
3828 EXPECT_EQ(OK, rv);
3829
3830 const HttpResponseInfo* response = trans->GetResponseInfo();
3831 EXPECT_FALSE(response == NULL);
3832
3833 std::string response_text;
3834 rv = ReadTransaction(trans.get(), &response_text);
3835 EXPECT_EQ(OK, rv);
3836 EXPECT_EQ("Payload", response_text);
3837}
3838
3839TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093840 SessionDependencies session_deps(
3841 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353842
3843 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433844 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353845
3846 HttpRequestInfo request;
3847 request.method = "GET";
3848 request.url = GURL("http://www.google.com/");
3849 request.load_flags = 0;
3850
3851 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3852 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373853 const char kSOCKS5OkRequest[] = {
3854 0x05, // Version
3855 0x01, // Command (CONNECT)
3856 0x00, // Reserved.
3857 0x03, // Address type (DOMAINNAME).
3858 0x0E, // Length of domain (14)
3859 // Domain string:
3860 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3861 0x00, 0x50, // 16-bit port (80)
3862 };
[email protected]e0c27be2009-07-15 13:09:353863 const char kSOCKS5OkResponse[] =
3864 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3865
3866 MockWrite data_writes[] = {
3867 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3868 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3869 MockWrite("GET / HTTP/1.1\r\n"
3870 "Host: www.google.com\r\n"
3871 "Connection: keep-alive\r\n\r\n")
3872 };
3873
3874 MockRead data_reads[] = {
3875 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3876 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3877 MockRead("HTTP/1.0 200 OK\r\n"),
3878 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3879 MockRead("Payload"),
3880 MockRead(false, OK)
3881 };
3882
[email protected]31a2bfe2010-02-09 08:03:393883 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3884 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593885 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353886
3887 TestCompletionCallback callback;
3888
[email protected]5a1d7ca2010-04-28 20:12:273889 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353890 EXPECT_EQ(ERR_IO_PENDING, rv);
3891
3892 rv = callback.WaitForResult();
3893 EXPECT_EQ(OK, rv);
3894
3895 const HttpResponseInfo* response = trans->GetResponseInfo();
3896 EXPECT_FALSE(response == NULL);
3897
3898 std::string response_text;
3899 rv = ReadTransaction(trans.get(), &response_text);
3900 EXPECT_EQ(OK, rv);
3901 EXPECT_EQ("Payload", response_text);
3902}
3903
3904TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093905 SessionDependencies session_deps(
3906 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353907
3908 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433909 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353910
3911 HttpRequestInfo request;
3912 request.method = "GET";
3913 request.url = GURL("https://www.google.com/");
3914 request.load_flags = 0;
3915
3916 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3917 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373918 const unsigned char kSOCKS5OkRequest[] = {
3919 0x05, // Version
3920 0x01, // Command (CONNECT)
3921 0x00, // Reserved.
3922 0x03, // Address type (DOMAINNAME).
3923 0x0E, // Length of domain (14)
3924 // Domain string:
3925 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3926 0x01, 0xBB, // 16-bit port (443)
3927 };
3928
[email protected]e0c27be2009-07-15 13:09:353929 const char kSOCKS5OkResponse[] =
3930 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3931
3932 MockWrite data_writes[] = {
3933 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3934 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3935 arraysize(kSOCKS5OkRequest)),
3936 MockWrite("GET / HTTP/1.1\r\n"
3937 "Host: www.google.com\r\n"
3938 "Connection: keep-alive\r\n\r\n")
3939 };
3940
3941 MockRead data_reads[] = {
3942 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3943 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023944 MockRead("HTTP/1.0 200 OK\r\n"),
3945 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3946 MockRead("Payload"),
3947 MockRead(false, OK)
3948 };
3949
[email protected]31a2bfe2010-02-09 08:03:393950 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3951 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593952 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023953
[email protected]5ecc992a42009-11-11 01:41:593954 SSLSocketDataProvider ssl(true, OK);
3955 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023956
3957 TestCompletionCallback callback;
3958
[email protected]5a1d7ca2010-04-28 20:12:273959 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023960 EXPECT_EQ(ERR_IO_PENDING, rv);
3961
3962 rv = callback.WaitForResult();
3963 EXPECT_EQ(OK, rv);
3964
3965 const HttpResponseInfo* response = trans->GetResponseInfo();
3966 EXPECT_FALSE(response == NULL);
3967
3968 std::string response_text;
3969 rv = ReadTransaction(trans.get(), &response_text);
3970 EXPECT_EQ(OK, rv);
3971 EXPECT_EQ("Payload", response_text);
3972}
3973
[email protected]04e5be32009-06-26 20:00:313974// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:063975
3976struct GroupNameTest {
3977 std::string proxy_server;
3978 std::string url;
3979 std::string expected_group_name;
3980};
3981
3982scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
3983 const std::string& proxy_server) {
3984 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
3985 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3986
3987 HttpAlternateProtocols* alternate_protocols =
3988 session->mutable_alternate_protocols();
3989 alternate_protocols->SetAlternateProtocolFor(
3990 HostPortPair("host.with.alternate", 80), 443,
3991 HttpAlternateProtocols::NPN_SPDY_1);
3992
3993 return session;
3994}
3995
3996int GroupNameTransactionHelper(
3997 const std::string& url,
3998 const scoped_refptr<HttpNetworkSession>& session) {
3999 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4000
4001 HttpRequestInfo request;
4002 request.method = "GET";
4003 request.url = GURL(url);
4004 request.load_flags = 0;
4005
4006 TestCompletionCallback callback;
4007
4008 // We do not complete this request, the dtor will clean the transaction up.
4009 return trans->Start(&request, &callback, BoundNetLog());
4010}
4011
4012TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
4013 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:314014 {
[email protected]2d731a32010-04-29 01:04:064015 "", // unused
[email protected]04e5be32009-06-26 20:00:314016 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544017 "www.google.com:80",
4018 },
4019 {
[email protected]2d731a32010-04-29 01:04:064020 "", // unused
[email protected]2ff8b312010-04-26 22:20:544021 "http://[2001:1418:13:1::25]/direct",
4022 "[2001:1418:13:1::25]:80",
[email protected]04e5be32009-06-26 20:00:314023 },
[email protected]04e5be32009-06-26 20:00:314024
4025 // SSL Tests
4026 {
[email protected]2d731a32010-04-29 01:04:064027 "", // unused
[email protected]04e5be32009-06-26 20:00:314028 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024029 "ssl/www.google.com:443",
[email protected]04e5be32009-06-26 20:00:314030 },
4031 {
[email protected]2d731a32010-04-29 01:04:064032 "", // unused
4033 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024034 "ssl/[2001:1418:13:1::25]:443",
[email protected]04e5be32009-06-26 20:00:314035 },
4036 {
[email protected]2d731a32010-04-29 01:04:064037 "", // unused
[email protected]2ff8b312010-04-26 22:20:544038 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024039 "ssl/host.with.alternate:443",
[email protected]2ff8b312010-04-26 22:20:544040 },
[email protected]2d731a32010-04-29 01:04:064041 };
[email protected]2ff8b312010-04-26 22:20:544042
[email protected]2d731a32010-04-29 01:04:064043 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4044
4045 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4046 scoped_refptr<HttpNetworkSession> session(
4047 SetupSessionForGroupNameTests(tests[i].proxy_server));
4048
4049 HttpNetworkSessionPeer peer(session);
4050 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
4051 new CaptureGroupNameTCPSocketPool(session.get()));
4052 peer.SetTCPSocketPool(tcp_conn_pool);
4053
4054 EXPECT_EQ(ERR_IO_PENDING,
4055 GroupNameTransactionHelper(tests[i].url, session));
4056 EXPECT_EQ(tests[i].expected_group_name,
4057 tcp_conn_pool->last_group_name_received());
4058 }
4059
4060 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4061}
4062
4063TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
4064 const GroupNameTest tests[] = {
4065 {
4066 "http_proxy",
4067 "http://www.google.com/http_proxy_normal",
4068 "www.google.com:80",
4069 },
4070
4071 // SSL Tests
4072 {
4073 "http_proxy",
4074 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024075 "ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064076 },
4077
[email protected]9faeded92010-04-29 20:03:054078 {
4079 "http_proxy",
4080 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024081 "ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:054082 },
[email protected]2d731a32010-04-29 01:04:064083 };
4084
4085 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4086
4087 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4088 scoped_refptr<HttpNetworkSession> session(
4089 SetupSessionForGroupNameTests(tests[i].proxy_server));
4090
4091 HttpNetworkSessionPeer peer(session);
4092
[email protected]e772db3f2010-07-12 18:11:134093 scoped_refptr<CaptureGroupNameHttpProxySocketPool> http_proxy_pool(
4094 new CaptureGroupNameHttpProxySocketPool(session.get()));
[email protected]2d731a32010-04-29 01:04:064095 peer.SetSocketPoolForHTTPProxy(
4096 HostPortPair("http_proxy", 80), http_proxy_pool);
4097
4098 EXPECT_EQ(ERR_IO_PENDING,
4099 GroupNameTransactionHelper(tests[i].url, session));
4100 EXPECT_EQ(tests[i].expected_group_name,
4101 http_proxy_pool->last_group_name_received());
4102 }
4103
4104 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4105}
4106
4107TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4108 const GroupNameTest tests[] = {
4109 {
4110 "socks4://socks_proxy:1080",
4111 "http://www.google.com/socks4_direct",
4112 "socks4/www.google.com:80",
4113 },
4114 {
4115 "socks5://socks_proxy:1080",
4116 "http://www.google.com/socks5_direct",
4117 "socks5/www.google.com:80",
4118 },
4119
4120 // SSL Tests
4121 {
4122 "socks4://socks_proxy:1080",
4123 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024124 "socks4/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064125 },
4126 {
4127 "socks5://socks_proxy:1080",
4128 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024129 "socks5/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064130 },
4131
[email protected]9faeded92010-04-29 20:03:054132 {
4133 "socks4://socks_proxy:1080",
4134 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024135 "socks4/ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:054136 },
[email protected]04e5be32009-06-26 20:00:314137 };
4138
[email protected]2ff8b312010-04-26 22:20:544139 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4140
[email protected]04e5be32009-06-26 20:00:314141 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064142 scoped_refptr<HttpNetworkSession> session(
4143 SetupSessionForGroupNameTests(tests[i].proxy_server));
4144 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314145
[email protected]a796bcec2010-03-22 17:17:264146 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064147 new CaptureGroupNameSOCKSSocketPool(session.get()));
4148 peer.SetSocketPoolForSOCKSProxy(
4149 HostPortPair("socks_proxy", 1080), socks_conn_pool);
[email protected]04e5be32009-06-26 20:00:314150
[email protected]5695b8c2009-09-30 21:36:434151 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314152
[email protected]2d731a32010-04-29 01:04:064153 EXPECT_EQ(ERR_IO_PENDING,
4154 GroupNameTransactionHelper(tests[i].url, session));
4155 EXPECT_EQ(tests[i].expected_group_name,
4156 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314157 }
[email protected]2ff8b312010-04-26 22:20:544158
4159 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:314160}
4161
[email protected]9172a982009-06-06 00:30:254162TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544163 SessionDependencies session_deps(
4164 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324165
[email protected]69719062010-01-05 20:09:214166 // This simulates failure resolving all hostnames; that means we will fail
4167 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324168 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4169
[email protected]9172a982009-06-06 00:30:254170 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434171 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254172
4173 HttpRequestInfo request;
4174 request.method = "GET";
4175 request.url = GURL("http://www.google.com/");
4176
4177 TestCompletionCallback callback;
4178
[email protected]5a1d7ca2010-04-28 20:12:274179 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254180 EXPECT_EQ(ERR_IO_PENDING, rv);
4181
[email protected]9172a982009-06-06 00:30:254182 rv = callback.WaitForResult();
4183 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4184}
4185
[email protected]f3e6c1e2009-06-15 20:52:124186// Host resolution observer used by
4187// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4188// resovle requests are issued with a referrer of |expected_referrer|.
4189class ResolutionReferrerObserver : public HostResolver::Observer {
4190 public:
4191 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4192 : expected_referrer_(expected_referrer),
4193 called_start_with_referrer_(false),
4194 called_finish_with_referrer_(false) {
4195 }
4196
4197 virtual void OnStartResolution(int id,
4198 const HostResolver::RequestInfo& info) {
4199 if (info.referrer() == expected_referrer_)
4200 called_start_with_referrer_ = true;
4201 }
4202
4203 virtual void OnFinishResolutionWithStatus(
4204 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4205 if (info.referrer() == expected_referrer_)
4206 called_finish_with_referrer_ = true;
4207 }
4208
[email protected]eb255d32009-06-17 02:11:034209 virtual void OnCancelResolution(int id,
4210 const HostResolver::RequestInfo& info ) {
4211 FAIL() << "Should not be cancelling any requests!";
4212 }
4213
[email protected]f3e6c1e2009-06-15 20:52:124214 bool did_complete_with_expected_referrer() const {
4215 return called_start_with_referrer_ && called_finish_with_referrer_;
4216 }
4217
4218 private:
4219 GURL expected_referrer_;
4220 bool called_start_with_referrer_;
4221 bool called_finish_with_referrer_;
4222
4223 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4224};
4225
4226// Make sure that when HostResolver::Resolve() is invoked, it passes through
4227// the "referrer". This is depended on by the DNS prefetch observer.
4228TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4229 GURL referrer = GURL("http://expected-referrer/");
4230 EXPECT_TRUE(referrer.is_valid());
4231 ResolutionReferrerObserver resolution_observer(referrer);
4232
4233 SessionDependencies session_deps;
4234 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434235 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124236
4237 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144238 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124239
4240 // Connect up a mock socket which will fail when reading.
4241 MockRead data_reads[] = {
4242 MockRead(false, ERR_FAILED),
4243 };
[email protected]31a2bfe2010-02-09 08:03:394244 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594245 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124246
4247 // Issue a request, containing an HTTP referrer.
4248 HttpRequestInfo request;
4249 request.method = "GET";
4250 request.referrer = referrer;
4251 request.url = GURL("http://www.google.com/");
4252
4253 // Run the request until it fails reading from the socket.
4254 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274255 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124256 EXPECT_EQ(ERR_IO_PENDING, rv);
4257 rv = callback.WaitForResult();
4258 EXPECT_EQ(ERR_FAILED, rv);
4259
4260 // Check that the host resolution observer saw |referrer|.
4261 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4262}
4263
[email protected]685af592010-05-11 19:31:244264// Base test to make sure that when the load flags for a request specify to
4265// bypass the cache, the DNS cache is not used.
4266void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284267 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324268
[email protected]a2c2fb92009-07-18 07:31:044269 // Select a host resolver that does caching.
4270 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324271
[email protected]3b9cca42009-06-16 01:08:284272 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434273 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284274
4275 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4276 // a synchronous lookup.)
4277 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144278 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464279 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274280 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284281 EXPECT_EQ(OK, rv);
4282
4283 // Verify that it was added to host cache, by doing a subsequent async lookup
4284 // and confirming it completes synchronously.
4285 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464286 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284287 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274288 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324289 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284290
4291 // Inject a failure the next time that "www.google.com" is resolved. This way
4292 // we can tell if the next lookup hit the cache, or the "network".
4293 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324294 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284295
4296 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4297 // first read -- this won't be reached as the host resolution will fail first.
4298 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394299 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594300 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284301
4302 // Issue a request, asking to bypass the cache(s).
4303 HttpRequestInfo request;
4304 request.method = "GET";
[email protected]685af592010-05-11 19:31:244305 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284306 request.url = GURL("http://www.google.com/");
4307
4308 // Run the request.
4309 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274310 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284311 ASSERT_EQ(ERR_IO_PENDING, rv);
4312 rv = callback.WaitForResult();
4313
4314 // If we bypassed the cache, we would have gotten a failure while resolving
4315 // "www.google.com".
4316 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4317}
4318
[email protected]685af592010-05-11 19:31:244319// There are multiple load flags that should trigger the host cache bypass.
4320// Test each in isolation:
4321TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4322 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4323}
4324
4325TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4326 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4327}
4328
4329TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
4330 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
4331}
4332
[email protected]0877e3d2009-10-17 22:29:574333// Make sure we can handle an error when writing the request.
4334TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4335 SessionDependencies session_deps;
4336 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4337
4338 HttpRequestInfo request;
4339 request.method = "GET";
4340 request.url = GURL("http://www.foo.com/");
4341 request.load_flags = 0;
4342
4343 MockWrite write_failure[] = {
4344 MockWrite(true, ERR_CONNECTION_RESET),
4345 };
[email protected]31a2bfe2010-02-09 08:03:394346 StaticSocketDataProvider data(NULL, 0,
4347 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594348 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574349
4350 TestCompletionCallback callback;
4351
4352 scoped_ptr<HttpTransaction> trans(
4353 new HttpNetworkTransaction(CreateSession(&session_deps)));
4354
[email protected]5a1d7ca2010-04-28 20:12:274355 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574356 EXPECT_EQ(ERR_IO_PENDING, rv);
4357
4358 rv = callback.WaitForResult();
4359 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4360}
4361
4362// Check that a connection closed after the start of the headers finishes ok.
4363TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4364 SessionDependencies session_deps;
4365 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4366
4367 HttpRequestInfo request;
4368 request.method = "GET";
4369 request.url = GURL("http://www.foo.com/");
4370 request.load_flags = 0;
4371
4372 MockRead data_reads[] = {
4373 MockRead("HTTP/1."),
4374 MockRead(false, OK),
4375 };
4376
[email protected]31a2bfe2010-02-09 08:03:394377 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594378 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574379
4380 TestCompletionCallback callback;
4381
4382 scoped_ptr<HttpTransaction> trans(
4383 new HttpNetworkTransaction(CreateSession(&session_deps)));
4384
[email protected]5a1d7ca2010-04-28 20:12:274385 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574386 EXPECT_EQ(ERR_IO_PENDING, rv);
4387
4388 rv = callback.WaitForResult();
4389 EXPECT_EQ(OK, rv);
4390
4391 const HttpResponseInfo* response = trans->GetResponseInfo();
4392 EXPECT_TRUE(response != NULL);
4393
4394 EXPECT_TRUE(response->headers != NULL);
4395 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4396
4397 std::string response_data;
4398 rv = ReadTransaction(trans.get(), &response_data);
4399 EXPECT_EQ(OK, rv);
4400 EXPECT_EQ("", response_data);
4401}
4402
4403// Make sure that a dropped connection while draining the body for auth
4404// restart does the right thing.
4405TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4406 SessionDependencies session_deps;
4407 scoped_ptr<HttpTransaction> trans(
4408 new HttpNetworkTransaction(CreateSession(&session_deps)));
4409
4410 HttpRequestInfo request;
4411 request.method = "GET";
4412 request.url = GURL("http://www.google.com/");
4413 request.load_flags = 0;
4414
4415 MockWrite data_writes1[] = {
4416 MockWrite("GET / HTTP/1.1\r\n"
4417 "Host: www.google.com\r\n"
4418 "Connection: keep-alive\r\n\r\n"),
4419 };
4420
4421 MockRead data_reads1[] = {
4422 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4423 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4424 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4425 MockRead("Content-Length: 14\r\n\r\n"),
4426 MockRead("Unauth"),
4427 MockRead(true, ERR_CONNECTION_RESET),
4428 };
4429
[email protected]31a2bfe2010-02-09 08:03:394430 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4431 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594432 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574433
4434 // After calling trans->RestartWithAuth(), this is the request we should
4435 // be issuing -- the final header line contains the credentials.
4436 MockWrite data_writes2[] = {
4437 MockWrite("GET / HTTP/1.1\r\n"
4438 "Host: www.google.com\r\n"
4439 "Connection: keep-alive\r\n"
4440 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4441 };
4442
4443 // Lastly, the server responds with the actual content.
4444 MockRead data_reads2[] = {
4445 MockRead("HTTP/1.1 200 OK\r\n"),
4446 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4447 MockRead("Content-Length: 100\r\n\r\n"),
4448 MockRead(false, OK),
4449 };
4450
[email protected]31a2bfe2010-02-09 08:03:394451 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4452 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594453 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574454
4455 TestCompletionCallback callback1;
4456
[email protected]5a1d7ca2010-04-28 20:12:274457 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574458 EXPECT_EQ(ERR_IO_PENDING, rv);
4459
4460 rv = callback1.WaitForResult();
4461 EXPECT_EQ(OK, rv);
4462
4463 const HttpResponseInfo* response = trans->GetResponseInfo();
4464 EXPECT_FALSE(response == NULL);
4465
4466 // The password prompt info should have been set in response->auth_challenge.
4467 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4468
4469 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4470 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4471 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4472
4473 TestCompletionCallback callback2;
4474
4475 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4476 EXPECT_EQ(ERR_IO_PENDING, rv);
4477
4478 rv = callback2.WaitForResult();
4479 EXPECT_EQ(OK, rv);
4480
4481 response = trans->GetResponseInfo();
4482 EXPECT_FALSE(response == NULL);
4483 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4484 EXPECT_EQ(100, response->headers->GetContentLength());
4485}
4486
4487// Test HTTPS connections going through a proxy that sends extra data.
4488TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4489 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4490
4491 HttpRequestInfo request;
4492 request.method = "GET";
4493 request.url = GURL("https://www.google.com/");
4494 request.load_flags = 0;
4495
4496 MockRead proxy_reads[] = {
4497 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4498 MockRead(false, OK)
4499 };
4500
[email protected]31a2bfe2010-02-09 08:03:394501 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594502 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574503
[email protected]5ecc992a42009-11-11 01:41:594504 session_deps.socket_factory.AddSocketDataProvider(&data);
4505 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574506
4507 TestCompletionCallback callback;
4508
4509 session_deps.socket_factory.ResetNextMockIndexes();
4510
4511 scoped_ptr<HttpTransaction> trans(
4512 new HttpNetworkTransaction(CreateSession(&session_deps)));
4513
[email protected]5a1d7ca2010-04-28 20:12:274514 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574515 EXPECT_EQ(ERR_IO_PENDING, rv);
4516
4517 rv = callback.WaitForResult();
4518 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4519}
4520
[email protected]e22e1362009-11-23 21:31:124521TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464522 SessionDependencies session_deps;
4523 scoped_ptr<HttpTransaction> trans(
4524 new HttpNetworkTransaction(CreateSession(&session_deps)));
4525
4526 HttpRequestInfo request;
4527 request.method = "GET";
4528 request.url = GURL("http://www.google.com/");
4529 request.load_flags = 0;
4530
[email protected]e22e1362009-11-23 21:31:124531 MockRead data_reads[] = {
4532 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4533 MockRead(false, OK),
4534 };
[email protected]9492e4a2010-02-24 00:58:464535
4536 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4537 session_deps.socket_factory.AddSocketDataProvider(&data);
4538
4539 TestCompletionCallback callback;
4540
[email protected]5a1d7ca2010-04-28 20:12:274541 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464542 EXPECT_EQ(ERR_IO_PENDING, rv);
4543
4544 EXPECT_EQ(OK, callback.WaitForResult());
4545
4546 const HttpResponseInfo* response = trans->GetResponseInfo();
4547 EXPECT_TRUE(response != NULL);
4548
4549 EXPECT_TRUE(response->headers != NULL);
4550 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4551
4552 std::string response_data;
4553 rv = ReadTransaction(trans.get(), &response_data);
4554 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124555}
4556
[email protected]95d88ffe2010-02-04 21:25:334557TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4558 SessionDependencies session_deps;
4559 scoped_ptr<HttpTransaction> trans(
4560 new HttpNetworkTransaction(CreateSession(&session_deps)));
4561
4562 HttpRequestInfo request;
4563 request.method = "POST";
4564 request.url = GURL("http://www.google.com/upload");
4565 request.upload_data = new UploadData;
4566 request.load_flags = 0;
4567
4568 FilePath temp_file_path;
4569 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4570 const uint64 kFakeSize = 100000; // file is actually blank
4571
4572 std::vector<UploadData::Element> elements;
4573 UploadData::Element element;
4574 element.SetToFilePath(temp_file_path);
4575 element.SetContentLength(kFakeSize);
4576 elements.push_back(element);
4577 request.upload_data->set_elements(elements);
4578 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4579
4580 MockRead data_reads[] = {
4581 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4582 MockRead("hello world"),
4583 MockRead(false, OK),
4584 };
[email protected]31a2bfe2010-02-09 08:03:394585 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334586 session_deps.socket_factory.AddSocketDataProvider(&data);
4587
4588 TestCompletionCallback callback;
4589
[email protected]5a1d7ca2010-04-28 20:12:274590 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334591 EXPECT_EQ(ERR_IO_PENDING, rv);
4592
4593 rv = callback.WaitForResult();
4594 EXPECT_EQ(OK, rv);
4595
4596 const HttpResponseInfo* response = trans->GetResponseInfo();
4597 EXPECT_TRUE(response != NULL);
4598
4599 EXPECT_TRUE(response->headers != NULL);
4600 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4601
4602 std::string response_data;
4603 rv = ReadTransaction(trans.get(), &response_data);
4604 EXPECT_EQ(OK, rv);
4605 EXPECT_EQ("hello world", response_data);
4606
4607 file_util::Delete(temp_file_path, false);
4608}
4609
[email protected]6624b4622010-03-29 19:58:364610TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4611 // If we try to upload an unreadable file, the network stack should report
4612 // the file size as zero and upload zero bytes for that file.
4613 SessionDependencies session_deps;
4614 scoped_ptr<HttpTransaction> trans(
4615 new HttpNetworkTransaction(CreateSession(&session_deps)));
4616
4617 FilePath temp_file;
4618 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4619 std::string temp_file_content("Unreadable file.");
4620 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4621 temp_file_content.length()));
4622 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4623
4624 HttpRequestInfo request;
4625 request.method = "POST";
4626 request.url = GURL("http://www.google.com/upload");
4627 request.upload_data = new UploadData;
4628 request.load_flags = 0;
4629
4630 std::vector<UploadData::Element> elements;
4631 UploadData::Element element;
4632 element.SetToFilePath(temp_file);
4633 elements.push_back(element);
4634 request.upload_data->set_elements(elements);
4635
4636 MockRead data_reads[] = {
4637 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4638 MockRead(false, OK),
4639 };
4640 MockWrite data_writes[] = {
4641 MockWrite("POST /upload HTTP/1.1\r\n"
4642 "Host: www.google.com\r\n"
4643 "Connection: keep-alive\r\n"
4644 "Content-Length: 0\r\n\r\n"),
4645 MockWrite(false, OK),
4646 };
4647 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4648 arraysize(data_writes));
4649 session_deps.socket_factory.AddSocketDataProvider(&data);
4650
4651 TestCompletionCallback callback;
4652
[email protected]5a1d7ca2010-04-28 20:12:274653 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364654 EXPECT_EQ(ERR_IO_PENDING, rv);
4655
4656 rv = callback.WaitForResult();
4657 EXPECT_EQ(OK, rv);
4658
4659 const HttpResponseInfo* response = trans->GetResponseInfo();
4660 EXPECT_TRUE(response != NULL);
4661 EXPECT_TRUE(response->headers != NULL);
4662 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4663
4664 file_util::Delete(temp_file, false);
4665}
4666
4667TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4668 SessionDependencies session_deps;
4669 scoped_ptr<HttpTransaction> trans(
4670 new HttpNetworkTransaction(CreateSession(&session_deps)));
4671
4672 FilePath temp_file;
4673 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4674 std::string temp_file_contents("Unreadable file.");
4675 std::string unreadable_contents(temp_file_contents.length(), '\0');
4676 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4677 temp_file_contents.length()));
4678
4679 HttpRequestInfo request;
4680 request.method = "POST";
4681 request.url = GURL("http://www.google.com/upload");
4682 request.upload_data = new UploadData;
4683 request.load_flags = 0;
4684
4685 std::vector<UploadData::Element> elements;
4686 UploadData::Element element;
4687 element.SetToFilePath(temp_file);
4688 elements.push_back(element);
4689 request.upload_data->set_elements(elements);
4690
4691 MockRead data_reads[] = {
4692 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4693 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4694 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4695
4696 MockRead("HTTP/1.1 200 OK\r\n"),
4697 MockRead("Content-Length: 0\r\n\r\n"),
4698 MockRead(false, OK),
4699 };
4700 MockWrite data_writes[] = {
4701 MockWrite("POST /upload HTTP/1.1\r\n"
4702 "Host: www.google.com\r\n"
4703 "Connection: keep-alive\r\n"
4704 "Content-Length: 16\r\n\r\n"),
4705 MockWrite(false, temp_file_contents.c_str()),
4706
4707 MockWrite("POST /upload HTTP/1.1\r\n"
4708 "Host: www.google.com\r\n"
4709 "Connection: keep-alive\r\n"
4710 "Content-Length: 16\r\n"
4711 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4712 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4713 MockWrite(false, OK),
4714 };
4715 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4716 arraysize(data_writes));
4717 session_deps.socket_factory.AddSocketDataProvider(&data);
4718
4719 TestCompletionCallback callback1;
4720
[email protected]5a1d7ca2010-04-28 20:12:274721 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364722 EXPECT_EQ(ERR_IO_PENDING, rv);
4723
4724 rv = callback1.WaitForResult();
4725 EXPECT_EQ(OK, rv);
4726
4727 const HttpResponseInfo* response = trans->GetResponseInfo();
4728 EXPECT_TRUE(response != NULL);
4729 EXPECT_TRUE(response->headers != NULL);
4730 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4731
4732 // The password prompt info should have been set in response->auth_challenge.
4733 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4734 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4735 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4736 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4737
4738 // Now make the file unreadable and try again.
4739 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4740
4741 TestCompletionCallback callback2;
4742
4743 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4744 EXPECT_EQ(ERR_IO_PENDING, rv);
4745
4746 rv = callback2.WaitForResult();
4747 EXPECT_EQ(OK, rv);
4748
4749 response = trans->GetResponseInfo();
4750 EXPECT_TRUE(response != NULL);
4751 EXPECT_TRUE(response->headers != NULL);
4752 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4753 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4754
4755 file_util::Delete(temp_file, false);
4756}
4757
[email protected]aeefc9e82010-02-19 16:18:274758// Tests that changes to Auth realms are treated like auth rejections.
4759TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4760 SessionDependencies session_deps;
4761 scoped_ptr<HttpTransaction> trans(
4762 new HttpNetworkTransaction(CreateSession(&session_deps)));
4763
4764 HttpRequestInfo request;
4765 request.method = "GET";
4766 request.url = GURL("http://www.google.com/");
4767 request.load_flags = 0;
4768
4769 // First transaction will request a resource and receive a Basic challenge
4770 // with realm="first_realm".
4771 MockWrite data_writes1[] = {
4772 MockWrite("GET / HTTP/1.1\r\n"
4773 "Host: www.google.com\r\n"
4774 "Connection: keep-alive\r\n"
4775 "\r\n"),
4776 };
4777 MockRead data_reads1[] = {
4778 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4779 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4780 "\r\n"),
4781 };
4782
4783 // After calling trans->RestartWithAuth(), provide an Authentication header
4784 // for first_realm. The server will reject and provide a challenge with
4785 // second_realm.
4786 MockWrite data_writes2[] = {
4787 MockWrite("GET / HTTP/1.1\r\n"
4788 "Host: www.google.com\r\n"
4789 "Connection: keep-alive\r\n"
4790 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4791 "\r\n"),
4792 };
4793 MockRead data_reads2[] = {
4794 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4795 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4796 "\r\n"),
4797 };
4798
4799 // This again fails, and goes back to first_realm. Make sure that the
4800 // entry is removed from cache.
4801 MockWrite data_writes3[] = {
4802 MockWrite("GET / HTTP/1.1\r\n"
4803 "Host: www.google.com\r\n"
4804 "Connection: keep-alive\r\n"
4805 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4806 "\r\n"),
4807 };
4808 MockRead data_reads3[] = {
4809 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4810 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4811 "\r\n"),
4812 };
4813
4814 // Try one last time (with the correct password) and get the resource.
4815 MockWrite data_writes4[] = {
4816 MockWrite("GET / HTTP/1.1\r\n"
4817 "Host: www.google.com\r\n"
4818 "Connection: keep-alive\r\n"
4819 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4820 "\r\n"),
4821 };
4822 MockRead data_reads4[] = {
4823 MockRead("HTTP/1.1 200 OK\r\n"
4824 "Content-Type: text/html; charset=iso-8859-1\r\n"
4825 "Content-Length: 100\r\n"
4826 "\r\n"),
4827 };
4828
4829 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4830 data_writes1, arraysize(data_writes1));
4831 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4832 data_writes2, arraysize(data_writes2));
4833 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4834 data_writes3, arraysize(data_writes3));
4835 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4836 data_writes4, arraysize(data_writes4));
4837 session_deps.socket_factory.AddSocketDataProvider(&data1);
4838 session_deps.socket_factory.AddSocketDataProvider(&data2);
4839 session_deps.socket_factory.AddSocketDataProvider(&data3);
4840 session_deps.socket_factory.AddSocketDataProvider(&data4);
4841
4842 TestCompletionCallback callback1;
4843
4844 // Issue the first request with Authorize headers. There should be a
4845 // password prompt for first_realm waiting to be filled in after the
4846 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:274847 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:274848 EXPECT_EQ(ERR_IO_PENDING, rv);
4849 rv = callback1.WaitForResult();
4850 EXPECT_EQ(OK, rv);
4851 const HttpResponseInfo* response = trans->GetResponseInfo();
4852 ASSERT_FALSE(response == NULL);
4853 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4854 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4855 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4856 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4857
4858 // Issue the second request with an incorrect password. There should be a
4859 // password prompt for second_realm waiting to be filled in after the
4860 // transaction completes.
4861 TestCompletionCallback callback2;
4862 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4863 EXPECT_EQ(ERR_IO_PENDING, rv);
4864 rv = callback2.WaitForResult();
4865 EXPECT_EQ(OK, rv);
4866 response = trans->GetResponseInfo();
4867 ASSERT_FALSE(response == NULL);
4868 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4869 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4870 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4871 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4872
4873 // Issue the third request with another incorrect password. There should be
4874 // a password prompt for first_realm waiting to be filled in. If the password
4875 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4876 // first_realm was not correctly removed.
4877 TestCompletionCallback callback3;
4878 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4879 EXPECT_EQ(ERR_IO_PENDING, rv);
4880 rv = callback3.WaitForResult();
4881 EXPECT_EQ(OK, rv);
4882 response = trans->GetResponseInfo();
4883 ASSERT_FALSE(response == NULL);
4884 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4885 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4886 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4887 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4888
4889 // Issue the fourth request with the correct password and username.
4890 TestCompletionCallback callback4;
4891 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4892 EXPECT_EQ(ERR_IO_PENDING, rv);
4893 rv = callback4.WaitForResult();
4894 EXPECT_EQ(OK, rv);
4895 response = trans->GetResponseInfo();
4896 ASSERT_FALSE(response == NULL);
4897 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4898}
4899
[email protected]564b4912010-03-09 16:30:424900TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424901 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:064902 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:424903
[email protected]564b4912010-03-09 16:30:424904 SessionDependencies session_deps;
4905
4906 MockRead data_reads[] = {
4907 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]31e2c69e2010-04-15 18:06:064908 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424909 MockRead("hello world"),
4910 MockRead(false, OK),
4911 };
4912
4913 HttpRequestInfo request;
4914 request.method = "GET";
4915 request.url = GURL("http://www.google.com/");
4916 request.load_flags = 0;
4917
4918 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4919
4920 session_deps.socket_factory.AddSocketDataProvider(&data);
4921
4922 TestCompletionCallback callback;
4923
4924 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4925 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4926
[email protected]5a1d7ca2010-04-28 20:12:274927 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424928 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534929
[email protected]564b4912010-03-09 16:30:424930 HostPortPair http_host_port_pair;
4931 http_host_port_pair.host = "www.google.com";
4932 http_host_port_pair.port = 80;
4933 const HttpAlternateProtocols& alternate_protocols =
4934 session->alternate_protocols();
4935 EXPECT_FALSE(
4936 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4937
4938 EXPECT_EQ(OK, callback.WaitForResult());
4939
4940 const HttpResponseInfo* response = trans->GetResponseInfo();
4941 ASSERT_TRUE(response != NULL);
4942 ASSERT_TRUE(response->headers != NULL);
4943 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:534944 EXPECT_FALSE(response->was_fetched_via_spdy);
4945 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:574946 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:424947
4948 std::string response_data;
4949 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4950 EXPECT_EQ("hello world", response_data);
4951
4952 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4953 const HttpAlternateProtocols::PortProtocolPair alternate =
4954 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4955 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4956 expected_alternate.port = 443;
[email protected]31e2c69e2010-04-15 18:06:064957 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_1;
[email protected]564b4912010-03-09 16:30:424958 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:424959
[email protected]31e2c69e2010-04-15 18:06:064960 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:424961 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:424962}
4963
4964TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:064965 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:424966 SessionDependencies session_deps;
4967
4968 HttpRequestInfo request;
4969 request.method = "GET";
4970 request.url = GURL("http://www.google.com/");
4971 request.load_flags = 0;
4972
4973 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4974 StaticSocketDataProvider first_data;
4975 first_data.set_connect_data(mock_connect);
4976 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4977
4978 MockRead data_reads[] = {
4979 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4980 MockRead("hello world"),
4981 MockRead(true, OK),
4982 };
4983 StaticSocketDataProvider second_data(
4984 data_reads, arraysize(data_reads), NULL, 0);
4985 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4986
4987 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4988 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4989 // http://crbug.com/37454.
4990 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4991
4992 TestCompletionCallback callback;
4993
4994 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4995
4996 HostPortPair http_host_port_pair;
4997 http_host_port_pair.host = "www.google.com";
4998 http_host_port_pair.port = 80;
4999 HttpAlternateProtocols* alternate_protocols =
5000 session->mutable_alternate_protocols();
5001 alternate_protocols->SetAlternateProtocolFor(
5002 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]31e2c69e2010-04-15 18:06:065003 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:425004
5005 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5006
[email protected]5a1d7ca2010-04-28 20:12:275007 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425008 EXPECT_EQ(ERR_IO_PENDING, rv);
5009 EXPECT_EQ(OK, callback.WaitForResult());
5010
5011 const HttpResponseInfo* response = trans->GetResponseInfo();
5012 ASSERT_TRUE(response != NULL);
5013 ASSERT_TRUE(response->headers != NULL);
5014 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5015
5016 std::string response_data;
5017 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5018 EXPECT_EQ("hello world", response_data);
5019
5020 ASSERT_TRUE(
5021 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
5022 const HttpAlternateProtocols::PortProtocolPair alternate =
5023 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
5024 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:065025 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425026}
5027
5028// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
5029// says that it does SPDY, but it just does the TLS handshake, but the NPN
5030// response does not indicate SPDY, so we just do standard HTTPS over the port.
5031// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
5032// on the original port.
[email protected]a2cb8122010-03-10 17:22:425033// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
5034// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:535035//
[email protected]a2cb8122010-03-10 17:22:425036// HttpRequestInfo request;
5037// request.method = "GET";
5038// request.url = GURL("http://www.google.com/");
5039// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:535040//
[email protected]a2cb8122010-03-10 17:22:425041// MockRead data_reads[] = {
5042// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5043// MockRead("hello world"),
5044// MockRead(true, OK),
5045// };
5046// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5047// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:535048//
[email protected]a2cb8122010-03-10 17:22:425049// SSLSocketDataProvider ssl(true, OK);
5050// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:535051//
[email protected]a2cb8122010-03-10 17:22:425052// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:535053//
[email protected]a2cb8122010-03-10 17:22:425054// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:535055//
[email protected]a2cb8122010-03-10 17:22:425056// HostPortPair http_host_port_pair;
5057// http_host_port_pair.host = "www.google.com";
5058// http_host_port_pair.port = 80;
5059// HttpAlternateProtocols* alternate_protocols =
5060// session->mutable_alternate_protocols();
5061// alternate_protocols->SetAlternateProtocolFor(
5062// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065063// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:535064//
[email protected]a2cb8122010-03-10 17:22:425065// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:535066//
[email protected]5a1d7ca2010-04-28 20:12:275067// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:425068// EXPECT_EQ(ERR_IO_PENDING, rv);
5069// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:535070//
[email protected]a2cb8122010-03-10 17:22:425071// const HttpResponseInfo* response = trans->GetResponseInfo();
5072// ASSERT_TRUE(response != NULL);
5073// ASSERT_TRUE(response->headers != NULL);
5074// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535075//
[email protected]a2cb8122010-03-10 17:22:425076// std::string response_data;
5077// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5078// EXPECT_EQ("hello world", response_data);
5079// }
5080
5081TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:065082 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]2ff8b312010-04-26 22:20:545083 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115084 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]564b4912010-03-09 16:30:425085 SessionDependencies session_deps;
5086
5087 HttpRequestInfo request;
5088 request.method = "GET";
5089 request.url = GURL("http://www.google.com/");
5090 request.load_flags = 0;
5091
[email protected]a2cb8122010-03-10 17:22:425092 StaticSocketDataProvider first_tcp_connect;
5093 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5094
5095 SSLSocketDataProvider ssl(true, OK);
5096 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5097
[email protected]564b4912010-03-09 16:30:425098 MockRead data_reads[] = {
5099 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5100 MockRead("hello world"),
5101 MockRead(true, OK),
5102 };
[email protected]a2cb8122010-03-10 17:22:425103 StaticSocketDataProvider fallback_data(
5104 data_reads, arraysize(data_reads), NULL, 0);
5105 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425106
5107 TestCompletionCallback callback;
5108
5109 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5110
5111 HostPortPair http_host_port_pair;
5112 http_host_port_pair.host = "www.google.com";
5113 http_host_port_pair.port = 80;
5114 HttpAlternateProtocols* alternate_protocols =
5115 session->mutable_alternate_protocols();
5116 alternate_protocols->SetAlternateProtocolFor(
5117 http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065118 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:425119
5120 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5121
[email protected]5a1d7ca2010-04-28 20:12:275122 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425123 EXPECT_EQ(ERR_IO_PENDING, rv);
5124 EXPECT_EQ(OK, callback.WaitForResult());
5125
5126 const HttpResponseInfo* response = trans->GetResponseInfo();
5127 ASSERT_TRUE(response != NULL);
5128 ASSERT_TRUE(response->headers != NULL);
5129 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5130
5131 std::string response_data;
5132 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5133 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:545134 HttpNetworkTransaction::SetNextProtos("");
5135 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5136}
5137
5138TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
5139 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5140 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115141 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545142 SessionDependencies session_deps;
5143
5144 HttpRequestInfo request;
5145 request.method = "GET";
5146 request.url = GURL("http://www.google.com/");
5147 request.load_flags = 0;
5148
5149 MockRead data_reads[] = {
5150 MockRead("HTTP/1.1 200 OK\r\n"),
5151 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5152 MockRead("hello world"),
5153 MockRead(true, OK),
5154 };
5155
5156 StaticSocketDataProvider first_transaction(
5157 data_reads, arraysize(data_reads), NULL, 0);
5158 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5159
5160 SSLSocketDataProvider ssl(true, OK);
5161 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5162 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535163 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545164 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5165
[email protected]75f30cc22010-06-28 21:41:385166 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0));
[email protected]e7f75092010-07-01 22:39:135167 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545168
[email protected]75f30cc22010-06-28 21:41:385169 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0));
[email protected]a4aeaf42010-06-30 19:57:285170 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame());
[email protected]2ff8b312010-04-26 22:20:545171 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135172 CreateMockRead(*resp),
5173 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545174 MockRead(true, 0, 0),
5175 };
5176
5177 scoped_refptr<DelayedSocketData> spdy_data(
5178 new DelayedSocketData(
5179 1, // wait for one write to finish before reading.
5180 spdy_reads, arraysize(spdy_reads),
5181 spdy_writes, arraysize(spdy_writes)));
5182 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5183
5184 TestCompletionCallback callback;
5185
5186 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5187 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5188
[email protected]5a1d7ca2010-04-28 20:12:275189 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545190 EXPECT_EQ(ERR_IO_PENDING, rv);
5191 EXPECT_EQ(OK, callback.WaitForResult());
5192
5193 const HttpResponseInfo* response = trans->GetResponseInfo();
5194 ASSERT_TRUE(response != NULL);
5195 ASSERT_TRUE(response->headers != NULL);
5196 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5197
5198 std::string response_data;
5199 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5200 EXPECT_EQ("hello world", response_data);
5201
5202 trans.reset(new HttpNetworkTransaction(session));
5203
[email protected]5a1d7ca2010-04-28 20:12:275204 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545205 EXPECT_EQ(ERR_IO_PENDING, rv);
5206 EXPECT_EQ(OK, callback.WaitForResult());
5207
5208 response = trans->GetResponseInfo();
5209 ASSERT_TRUE(response != NULL);
5210 ASSERT_TRUE(response->headers != NULL);
5211 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535212 EXPECT_TRUE(response->was_fetched_via_spdy);
5213 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575214 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545215
5216 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5217 EXPECT_EQ("hello!", response_data);
5218
5219 HttpNetworkTransaction::SetNextProtos("");
5220 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5221}
5222
[email protected]631f1322010-04-30 17:59:115223class CapturingProxyResolver : public ProxyResolver {
5224 public:
5225 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5226 virtual ~CapturingProxyResolver() {}
5227
5228 virtual int GetProxyForURL(const GURL& url,
5229 ProxyInfo* results,
5230 CompletionCallback* callback,
5231 RequestHandle* request,
5232 const BoundNetLog& net_log) {
[email protected]d911f1b2010-05-05 22:39:425233 ProxyServer proxy_server(
5234 ProxyServer::SCHEME_HTTP, "myproxy", 80);
5235 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115236 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425237 return OK;
[email protected]631f1322010-04-30 17:59:115238 }
5239
5240 virtual void CancelRequest(RequestHandle request) {
5241 NOTREACHED();
5242 }
5243
5244 const std::vector<GURL>& resolved() const { return resolved_; }
5245
5246 private:
5247 virtual int SetPacScript(const GURL& /*pac_url*/,
[email protected]9b9ae9552010-07-01 22:20:505248 const string16& /*pac_script*/,
[email protected]631f1322010-04-30 17:59:115249 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425250 return OK;
[email protected]631f1322010-04-30 17:59:115251 }
5252
5253 std::vector<GURL> resolved_;
5254
5255 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5256};
5257
[email protected]631f1322010-04-30 17:59:115258TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
5259 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5260 HttpNetworkTransaction::SetNextProtos(
5261 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
5262
5263 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425264 proxy_config.set_auto_detect(true);
5265 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115266
[email protected]631f1322010-04-30 17:59:115267 CapturingProxyResolver* capturing_proxy_resolver =
5268 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:385269 SessionDependencies session_deps(new ProxyService(
5270 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
5271 NULL));
[email protected]631f1322010-04-30 17:59:115272
5273 HttpRequestInfo request;
5274 request.method = "GET";
5275 request.url = GURL("http://www.google.com/");
5276 request.load_flags = 0;
5277
5278 MockRead data_reads[] = {
5279 MockRead("HTTP/1.1 200 OK\r\n"),
5280 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5281 MockRead("hello world"),
5282 MockRead(true, OK),
5283 };
5284
5285 StaticSocketDataProvider first_transaction(
5286 data_reads, arraysize(data_reads), NULL, 0);
5287 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5288
5289 SSLSocketDataProvider ssl(true, OK);
5290 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5291 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535292 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:115293 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5294
[email protected]75f30cc22010-06-28 21:41:385295 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0));
[email protected]631f1322010-04-30 17:59:115296 MockWrite spdy_writes[] = {
5297 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5298 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425299 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:135300 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:115301 };
5302
[email protected]d911f1b2010-05-05 22:39:425303 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5304
[email protected]75f30cc22010-06-28 21:41:385305 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0));
[email protected]a4aeaf42010-06-30 19:57:285306 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame());
[email protected]631f1322010-04-30 17:59:115307 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425308 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:135309 CreateMockRead(*resp.get(), 4), // 2, 4
5310 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:425311 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115312 };
5313
[email protected]d911f1b2010-05-05 22:39:425314 scoped_refptr<OrderedSocketData> spdy_data(
5315 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115316 spdy_reads, arraysize(spdy_reads),
5317 spdy_writes, arraysize(spdy_writes)));
5318 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5319
5320 TestCompletionCallback callback;
5321
5322 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5323 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5324
5325 int rv = trans->Start(&request, &callback, BoundNetLog());
5326 EXPECT_EQ(ERR_IO_PENDING, rv);
5327 EXPECT_EQ(OK, callback.WaitForResult());
5328
5329 const HttpResponseInfo* response = trans->GetResponseInfo();
5330 ASSERT_TRUE(response != NULL);
5331 ASSERT_TRUE(response->headers != NULL);
5332 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535333 EXPECT_FALSE(response->was_fetched_via_spdy);
5334 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115335
5336 std::string response_data;
5337 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5338 EXPECT_EQ("hello world", response_data);
5339
5340 trans.reset(new HttpNetworkTransaction(session));
5341
5342 rv = trans->Start(&request, &callback, BoundNetLog());
5343 EXPECT_EQ(ERR_IO_PENDING, rv);
5344 EXPECT_EQ(OK, callback.WaitForResult());
5345
5346 response = trans->GetResponseInfo();
5347 ASSERT_TRUE(response != NULL);
5348 ASSERT_TRUE(response->headers != NULL);
5349 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535350 EXPECT_TRUE(response->was_fetched_via_spdy);
5351 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115352
5353 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5354 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425355 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5356 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115357 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425358 EXPECT_EQ("https://www.google.com/",
5359 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115360
5361 HttpNetworkTransaction::SetNextProtos("");
5362 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5363}
[email protected]631f1322010-04-30 17:59:115364
[email protected]2ff8b312010-04-26 22:20:545365TEST_F(HttpNetworkTransactionTest,
5366 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5367 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5368 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115369 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545370 SessionDependencies session_deps;
5371
5372 HttpRequestInfo request;
5373 request.method = "GET";
5374 request.url = GURL("http://www.google.com/");
5375 request.load_flags = 0;
5376
5377 MockRead data_reads[] = {
5378 MockRead("HTTP/1.1 200 OK\r\n"),
5379 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5380 MockRead("hello world"),
5381 MockRead(true, OK),
5382 };
5383
5384 StaticSocketDataProvider first_transaction(
5385 data_reads, arraysize(data_reads), NULL, 0);
5386 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5387
5388 SSLSocketDataProvider ssl(true, OK);
5389 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5390 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535391 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545392 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:535393 // Make sure we use ssl for spdy here.
5394 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:545395
[email protected]75f30cc22010-06-28 21:41:385396 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0));
[email protected]e7f75092010-07-01 22:39:135397 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545398
[email protected]75f30cc22010-06-28 21:41:385399 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0));
[email protected]a4aeaf42010-06-30 19:57:285400 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame());
[email protected]2ff8b312010-04-26 22:20:545401 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135402 CreateMockRead(*resp),
5403 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545404 MockRead(true, 0, 0),
5405 };
5406
5407 scoped_refptr<DelayedSocketData> spdy_data(
5408 new DelayedSocketData(
5409 1, // wait for one write to finish before reading.
5410 spdy_reads, arraysize(spdy_reads),
5411 spdy_writes, arraysize(spdy_writes)));
5412 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5413
5414 TestCompletionCallback callback;
5415
5416 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5417
5418 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5419
[email protected]5a1d7ca2010-04-28 20:12:275420 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545421 EXPECT_EQ(ERR_IO_PENDING, rv);
5422 EXPECT_EQ(OK, callback.WaitForResult());
5423
5424 const HttpResponseInfo* response = trans->GetResponseInfo();
5425 ASSERT_TRUE(response != NULL);
5426 ASSERT_TRUE(response->headers != NULL);
5427 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5428
5429 std::string response_data;
5430 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5431 EXPECT_EQ("hello world", response_data);
5432
5433 // Set up an initial SpdySession in the pool to reuse.
5434 scoped_refptr<SpdySession> spdy_session =
5435 session->spdy_session_pool()->Get(HostPortPair("www.google.com", 443),
[email protected]635909f2010-05-12 18:19:365436 session, BoundNetLog());
[email protected]df4b4ef2010-07-12 18:25:215437 scoped_refptr<TCPSocketParams> tcp_params =
5438 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:365439 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:545440 trans.reset(new HttpNetworkTransaction(session));
5441
[email protected]5a1d7ca2010-04-28 20:12:275442 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545443 EXPECT_EQ(ERR_IO_PENDING, rv);
5444 EXPECT_EQ(OK, callback.WaitForResult());
5445
5446 response = trans->GetResponseInfo();
5447 ASSERT_TRUE(response != NULL);
5448 ASSERT_TRUE(response->headers != NULL);
5449 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535450 EXPECT_TRUE(response->was_fetched_via_spdy);
5451 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575452 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545453
5454 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5455 EXPECT_EQ("hello!", response_data);
5456
5457 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065458 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425459}
5460
[email protected]044de0642010-06-17 10:42:155461// GenerateAuthToken is a mighty big test.
5462// It tests all permutation of GenerateAuthToken behavior:
5463// - Synchronous and Asynchronous completion.
5464// - OK or error on completion.
5465// - Direct connection, non-authenticating proxy, and authenticating proxy.
5466// - HTTP or HTTPS backend (to include proxy tunneling).
5467// - Non-authenticating and authenticating backend.
5468//
5469// In all, there are 44 reasonable permuations (for example, if there are
5470// problems generating an auth token for an authenticating proxy, we don't
5471// need to test all permutations of the backend server).
5472//
5473// The test proceeds by going over each of the configuration cases, and
5474// potentially running up to three rounds in each of the tests. The TestConfig
5475// specifies both the configuration for the test as well as the expectations
5476// for the results.
5477TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
5478 const char* kServer = "http://www.example.com";
5479 const char* kSecureServer = "https://www.example.com";
5480 const char* kProxy = "myproxy:70";
5481 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
5482
5483 enum AuthTiming {
5484 AUTH_NONE,
5485 AUTH_SYNC,
5486 AUTH_ASYNC,
5487 };
5488
5489 const MockWrite kGet(
5490 "GET / HTTP/1.1\r\n"
5491 "Host: www.example.com\r\n"
5492 "Connection: keep-alive\r\n\r\n");
5493 const MockWrite kGetProxy(
5494 "GET http://www.example.com/ HTTP/1.1\r\n"
5495 "Host: www.example.com\r\n"
5496 "Proxy-Connection: keep-alive\r\n\r\n");
5497 const MockWrite kGetAuth(
5498 "GET / HTTP/1.1\r\n"
5499 "Host: www.example.com\r\n"
5500 "Connection: keep-alive\r\n"
5501 "Authorization: auth_token\r\n\r\n");
5502 const MockWrite kGetProxyAuth(
5503 "GET http://www.example.com/ HTTP/1.1\r\n"
5504 "Host: www.example.com\r\n"
5505 "Proxy-Connection: keep-alive\r\n"
5506 "Proxy-Authorization: auth_token\r\n\r\n");
5507 const MockWrite kGetAuthThroughProxy(
5508 "GET http://www.example.com/ HTTP/1.1\r\n"
5509 "Host: www.example.com\r\n"
5510 "Proxy-Connection: keep-alive\r\n"
5511 "Authorization: auth_token\r\n\r\n");
5512 const MockWrite kGetAuthWithProxyAuth(
5513 "GET http://www.example.com/ HTTP/1.1\r\n"
5514 "Host: www.example.com\r\n"
5515 "Proxy-Connection: keep-alive\r\n"
5516 "Proxy-Authorization: auth_token\r\n"
5517 "Authorization: auth_token\r\n\r\n");
5518 const MockWrite kConnect(
5519 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5520 "Host: www.example.com\r\n"
5521 "Proxy-Connection: keep-alive\r\n\r\n");
5522 const MockWrite kConnectProxyAuth(
5523 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5524 "Host: www.example.com\r\n"
5525 "Proxy-Connection: keep-alive\r\n"
5526 "Proxy-Authorization: auth_token\r\n\r\n");
5527
5528 const MockRead kSuccess(
5529 "HTTP/1.1 200 OK\r\n"
5530 "Content-Type: text/html; charset=iso-8859-1\r\n"
5531 "Content-Length: 3\r\n\r\n"
5532 "Yes");
5533 const MockRead kFailure(
5534 "Should not be called.");
5535 const MockRead kServerChallenge(
5536 "HTTP/1.1 401 Unauthorized\r\n"
5537 "WWW-Authenticate: Mock realm=server\r\n"
5538 "Content-Type: text/html; charset=iso-8859-1\r\n"
5539 "Content-Length: 14\r\n\r\n"
5540 "Unauthorized\r\n");
5541 const MockRead kProxyChallenge(
5542 "HTTP/1.1 407 Unauthorized\r\n"
5543 "Proxy-Authenticate: Mock realm=proxy\r\n"
5544 "Proxy-Connection: close\r\n"
5545 "Content-Type: text/html; charset=iso-8859-1\r\n"
5546 "Content-Length: 14\r\n\r\n"
5547 "Unauthorized\r\n");
5548 const MockRead kProxyConnected(
5549 "HTTP/1.1 200 Connection Established\r\n\r\n");
5550
5551 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
5552 // no constructors, but the C++ compiler on Windows warns about
5553 // unspecified data in compound literals. So, moved to using constructors,
5554 // and TestRound's created with the default constructor should not be used.
5555 struct TestRound {
5556 TestRound()
5557 : expected_rv(ERR_UNEXPECTED),
5558 extra_write(NULL),
5559 extra_read(NULL) {
5560 }
5561 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5562 int expected_rv_arg)
5563 : write(write_arg),
5564 read(read_arg),
5565 expected_rv(expected_rv_arg),
5566 extra_write(NULL),
5567 extra_read(NULL) {
5568 }
5569 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5570 int expected_rv_arg, const MockWrite* extra_write_arg,
5571 const MockWrite* extra_read_arg)
5572 : write(write_arg),
5573 read(read_arg),
5574 expected_rv(expected_rv_arg),
5575 extra_write(extra_write_arg),
5576 extra_read(extra_read_arg) {
5577 }
5578 MockWrite write;
5579 MockRead read;
5580 int expected_rv;
5581 const MockWrite* extra_write;
5582 const MockRead* extra_read;
5583 };
5584
5585 static const int kNoSSL = 500;
5586
5587 struct TestConfig {
5588 const char* proxy_url;
5589 AuthTiming proxy_auth_timing;
5590 int proxy_auth_rv;
5591 const char* server_url;
5592 AuthTiming server_auth_timing;
5593 int server_auth_rv;
5594 int num_auth_rounds;
5595 int first_ssl_round;
5596 TestRound rounds[3];
5597 } test_configs[] = {
5598 // Non-authenticating HTTP server with a direct connection.
5599 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5600 { TestRound(kGet, kSuccess, OK)}},
5601 // Authenticating HTTP server with a direct connection.
5602 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5603 { TestRound(kGet, kServerChallenge, OK),
5604 TestRound(kGetAuth, kSuccess, OK)}},
5605 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5606 { TestRound(kGet, kServerChallenge, OK),
5607 TestRound(kGetAuth, kFailure, kAuthErr)}},
5608 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5609 { TestRound(kGet, kServerChallenge, OK),
5610 TestRound(kGetAuth, kSuccess, OK)}},
5611 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5612 { TestRound(kGet, kServerChallenge, OK),
5613 TestRound(kGetAuth, kFailure, kAuthErr)}},
5614 // Non-authenticating HTTP server through a non-authenticating proxy.
5615 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5616 { TestRound(kGetProxy, kSuccess, OK)}},
5617 // Authenticating HTTP server through a non-authenticating proxy.
5618 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5619 { TestRound(kGetProxy, kServerChallenge, OK),
5620 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5621 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5622 { TestRound(kGetProxy, kServerChallenge, OK),
5623 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5624 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5625 { TestRound(kGetProxy, kServerChallenge, OK),
5626 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5627 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5628 { TestRound(kGetProxy, kServerChallenge, OK),
5629 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5630 // Non-authenticating HTTP server through an authenticating proxy.
5631 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5632 { TestRound(kGetProxy, kProxyChallenge, OK),
5633 TestRound(kGetProxyAuth, kSuccess, OK)}},
5634 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5635 { TestRound(kGetProxy, kProxyChallenge, OK),
5636 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5637 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5638 { TestRound(kGetProxy, kProxyChallenge, OK),
5639 TestRound(kGetProxyAuth, kSuccess, OK)}},
5640 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5641 { TestRound(kGetProxy, kProxyChallenge, OK),
5642 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5643 // Authenticating HTTP server through an authenticating proxy.
5644 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5645 { TestRound(kGetProxy, kProxyChallenge, OK),
5646 TestRound(kGetProxyAuth, kServerChallenge, OK),
5647 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5648 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5649 { TestRound(kGetProxy, kProxyChallenge, OK),
5650 TestRound(kGetProxyAuth, kServerChallenge, OK),
5651 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5652 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5653 { TestRound(kGetProxy, kProxyChallenge, OK),
5654 TestRound(kGetProxyAuth, kServerChallenge, OK),
5655 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5656 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5657 { TestRound(kGetProxy, kProxyChallenge, OK),
5658 TestRound(kGetProxyAuth, kServerChallenge, OK),
5659 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5660 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5661 { TestRound(kGetProxy, kProxyChallenge, OK),
5662 TestRound(kGetProxyAuth, kServerChallenge, OK),
5663 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5664 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5665 { TestRound(kGetProxy, kProxyChallenge, OK),
5666 TestRound(kGetProxyAuth, kServerChallenge, OK),
5667 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5668 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5669 { TestRound(kGetProxy, kProxyChallenge, OK),
5670 TestRound(kGetProxyAuth, kServerChallenge, OK),
5671 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5672 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5673 { TestRound(kGetProxy, kProxyChallenge, OK),
5674 TestRound(kGetProxyAuth, kServerChallenge, OK),
5675 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5676 // Non-authenticating HTTPS server with a direct connection.
5677 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5678 { TestRound(kGet, kSuccess, OK)}},
5679 // Authenticating HTTPS server with a direct connection.
5680 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5681 { TestRound(kGet, kServerChallenge, OK),
5682 TestRound(kGetAuth, kSuccess, OK)}},
5683 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5684 { TestRound(kGet, kServerChallenge, OK),
5685 TestRound(kGetAuth, kFailure, kAuthErr)}},
5686 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5687 { TestRound(kGet, kServerChallenge, OK),
5688 TestRound(kGetAuth, kSuccess, OK)}},
5689 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5690 { TestRound(kGet, kServerChallenge, OK),
5691 TestRound(kGetAuth, kFailure, kAuthErr)}},
5692 // Non-authenticating HTTPS server with a non-authenticating proxy.
5693 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5694 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
5695 // Authenticating HTTPS server through a non-authenticating proxy.
5696 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5697 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5698 TestRound(kGetAuth, kSuccess, OK)}},
5699 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5700 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5701 TestRound(kGetAuth, kFailure, kAuthErr)}},
5702 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5703 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5704 TestRound(kGetAuth, kSuccess, OK)}},
5705 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5706 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5707 TestRound(kGetAuth, kFailure, kAuthErr)}},
5708 // Non-Authenticating HTTPS server through an authenticating proxy.
5709 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5710 { TestRound(kConnect, kProxyChallenge, OK),
5711 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5712 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5713 { TestRound(kConnect, kProxyChallenge, OK),
5714 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5715 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5716 { TestRound(kConnect, kProxyChallenge, OK),
5717 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5718 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5719 { TestRound(kConnect, kProxyChallenge, OK),
5720 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5721 // Authenticating HTTPS server through an authenticating proxy.
5722 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5723 { TestRound(kConnect, kProxyChallenge, OK),
5724 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5725 &kGet, &kServerChallenge),
5726 TestRound(kGetAuth, kSuccess, OK)}},
5727 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5728 { TestRound(kConnect, kProxyChallenge, OK),
5729 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5730 &kGet, &kServerChallenge),
5731 TestRound(kGetAuth, kFailure, kAuthErr)}},
5732 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5733 { TestRound(kConnect, kProxyChallenge, OK),
5734 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5735 &kGet, &kServerChallenge),
5736 TestRound(kGetAuth, kSuccess, OK)}},
5737 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5738 { TestRound(kConnect, kProxyChallenge, OK),
5739 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5740 &kGet, &kServerChallenge),
5741 TestRound(kGetAuth, kFailure, kAuthErr)}},
5742 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5743 { TestRound(kConnect, kProxyChallenge, OK),
5744 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5745 &kGet, &kServerChallenge),
5746 TestRound(kGetAuth, kSuccess, OK)}},
5747 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5748 { TestRound(kConnect, kProxyChallenge, OK),
5749 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5750 &kGet, &kServerChallenge),
5751 TestRound(kGetAuth, kFailure, kAuthErr)}},
5752 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5753 { TestRound(kConnect, kProxyChallenge, OK),
5754 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5755 &kGet, &kServerChallenge),
5756 TestRound(kGetAuth, kSuccess, OK)}},
5757 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5758 { TestRound(kConnect, kProxyChallenge, OK),
5759 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5760 &kGet, &kServerChallenge),
5761 TestRound(kGetAuth, kFailure, kAuthErr)}},
5762 };
5763
5764 SessionDependencies session_deps;
5765 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]3fd9dae2010-06-21 11:39:005766 HttpAuthHandlerMock::Factory* auth_factory(
5767 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:155768 session_deps.http_auth_handler_factory.reset(auth_factory);
5769
5770 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
5771 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:265772
5773 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:155774 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005775 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155776 std::string auth_challenge = "Mock realm=proxy";
5777 GURL origin(test_config.proxy_url);
5778 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5779 auth_challenge.end());
5780 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
5781 origin, BoundNetLog());
5782 auth_handler->SetGenerateExpectation(
5783 test_config.proxy_auth_timing == AUTH_ASYNC,
5784 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:155785 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
5786 }
5787 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005788 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155789 std::string auth_challenge = "Mock realm=server";
5790 GURL origin(test_config.server_url);
5791 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5792 auth_challenge.end());
5793 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
5794 origin, BoundNetLog());
5795 auth_handler->SetGenerateExpectation(
5796 test_config.server_auth_timing == AUTH_ASYNC,
5797 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:155798 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
5799 }
5800 if (test_config.proxy_url) {
5801 session_deps.proxy_service =
5802 CreateFixedProxyService(test_config.proxy_url);
5803 } else {
5804 session_deps.proxy_service = ProxyService::CreateNull();
5805 }
5806
5807 HttpRequestInfo request;
5808 request.method = "GET";
5809 request.url = GURL(test_config.server_url);
5810 request.load_flags = 0;
5811
5812 scoped_ptr<HttpTransaction> trans(
5813 new HttpNetworkTransaction(CreateSession(&session_deps)));
5814
5815 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
5816 const TestRound& read_write_round = test_config.rounds[round];
5817
5818 // Set up expected reads and writes.
5819 MockRead reads[2];
5820 reads[0] = read_write_round.read;
5821 size_t length_reads = 1;
5822 if (read_write_round.extra_read) {
5823 reads[1] = *read_write_round.extra_read;
5824 length_reads = 2;
5825 }
5826
5827 MockWrite writes[2];
5828 writes[0] = read_write_round.write;
5829 size_t length_writes = 1;
5830 if (read_write_round.extra_write) {
5831 writes[1] = *read_write_round.extra_write;
5832 length_writes = 2;
5833 }
5834 StaticSocketDataProvider data_provider(
5835 reads, length_reads, writes, length_writes);
5836 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
5837
5838 // Add an SSL sequence if necessary.
5839 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
5840 if (round >= test_config.first_ssl_round)
5841 session_deps.socket_factory.AddSSLSocketDataProvider(
5842 &ssl_socket_data_provider);
5843
5844 // Start or restart the transaction.
5845 TestCompletionCallback callback;
5846 int rv;
5847 if (round == 0) {
5848 rv = trans->Start(&request, &callback, BoundNetLog());
5849 } else {
5850 rv = trans->RestartWithAuth(L"foo", L"bar", &callback);
5851 }
5852 if (rv == ERR_IO_PENDING)
5853 rv = callback.WaitForResult();
5854
5855 // Compare results with expected data.
5856 EXPECT_EQ(read_write_round.expected_rv, rv);
5857 const HttpResponseInfo* response = trans->GetResponseInfo();
5858 if (read_write_round.expected_rv == OK) {
5859 EXPECT_FALSE(response == NULL);
5860 } else {
5861 EXPECT_TRUE(response == NULL);
5862 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
5863 continue;
5864 }
5865 if (round + 1 < test_config.num_auth_rounds) {
5866 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5867 } else {
5868 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5869 }
5870 }
[email protected]e5ae96a2010-04-14 20:12:455871 }
5872}
5873
[email protected]aeaca1f2010-04-20 22:05:215874class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
5875 public:
[email protected]06650c52010-06-03 00:49:175876 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:215877 : fail_all_(fail_all) {
5878 }
5879
5880 virtual MockRead GetNextRead() {
5881 if (fail_all_)
5882 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
5883
5884 return MockRead(false /* async */,
5885 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
5886 }
5887
5888 virtual MockWriteResult OnWrite(const std::string& data) {
5889 return MockWriteResult(false /* async */, data.size());
5890 }
5891
5892 void Reset() {
5893 }
5894
5895 private:
5896 const bool fail_all_;
5897};
5898
5899// Test that we restart a connection when we see a decompression failure from
5900// the peer during the handshake. (In the real world we'll restart with SSLv3
5901// and we won't offer DEFLATE in that case.)
5902TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
5903 HttpRequestInfo request;
5904 request.method = "GET";
5905 request.url = GURL("https://tlsdecompressionfailure.example.com/");
5906 request.load_flags = 0;
5907
5908 SessionDependencies session_deps;
5909 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5910 false /* fail all reads */);
5911 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5912 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:115913 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:215914 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5915 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5916 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5917 session_deps.socket_factory.AddSSLSocketDataProvider(
5918 &ssl_socket_data_provider1);
5919 session_deps.socket_factory.AddSSLSocketDataProvider(
5920 &ssl_socket_data_provider2);
5921
5922 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5923 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5924 TestCompletionCallback callback;
5925
[email protected]5a1d7ca2010-04-28 20:12:275926 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:215927 EXPECT_EQ(ERR_IO_PENDING, rv);
5928 EXPECT_EQ(OK, callback.WaitForResult());
5929
5930 const HttpResponseInfo* response = trans->GetResponseInfo();
5931 ASSERT_TRUE(response != NULL);
5932 ASSERT_TRUE(response->headers != NULL);
5933 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5934
5935 std::string response_data;
5936 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5937 EXPECT_EQ("ok.", response_data);
5938}
5939
5940// Test that we restart a connection if we get a decompression failure from the
5941// peer while reading the first bytes from the connection. This occurs when the
5942// peer cannot handle DEFLATE but we're using False Start, so we don't notice
5943// in the handshake.
5944TEST_F(HttpNetworkTransactionTest,
5945 RestartAfterTLSDecompressionFailureWithFalseStart) {
5946 HttpRequestInfo request;
5947 request.method = "GET";
5948 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
5949 request.load_flags = 0;
5950
5951 SessionDependencies session_deps;
5952 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5953 true /* fail all reads */);
5954 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5955 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
5956 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5957 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5958 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5959 session_deps.socket_factory.AddSSLSocketDataProvider(
5960 &ssl_socket_data_provider1);
5961 session_deps.socket_factory.AddSSLSocketDataProvider(
5962 &ssl_socket_data_provider2);
5963
5964 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5965 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5966 TestCompletionCallback callback;
5967
[email protected]5a1d7ca2010-04-28 20:12:275968 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:215969 EXPECT_EQ(ERR_IO_PENDING, rv);
5970 EXPECT_EQ(OK, callback.WaitForResult());
5971
5972 const HttpResponseInfo* response = trans->GetResponseInfo();
5973 ASSERT_TRUE(response != NULL);
5974 ASSERT_TRUE(response->headers != NULL);
5975 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5976
5977 std::string response_data;
5978 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5979 EXPECT_EQ("ok.", response_data);
5980}
5981
[email protected]65041fa2010-05-21 06:56:535982// This tests the case that a request is issued via http instead of spdy after
5983// npn is negotiated.
5984TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
5985 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5986 HttpNetworkTransaction::SetNextProtos("\x08http/1.1\x07http1.1");
5987 SessionDependencies session_deps;
5988 HttpRequestInfo request;
5989 request.method = "GET";
5990 request.url = GURL("https://www.google.com/");
5991 request.load_flags = 0;
5992
5993 MockWrite data_writes[] = {
5994 MockWrite("GET / HTTP/1.1\r\n"
5995 "Host: www.google.com\r\n"
5996 "Connection: keep-alive\r\n\r\n"),
5997 };
5998
5999 MockRead data_reads[] = {
6000 MockRead("HTTP/1.1 200 OK\r\n"),
6001 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
6002 MockRead("hello world"),
6003 MockRead(false, OK),
6004 };
6005
6006 SSLSocketDataProvider ssl(true, OK);
6007 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6008 ssl.next_proto = "http/1.1";
6009
6010 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6011
6012 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6013 data_writes, arraysize(data_writes));
6014 session_deps.socket_factory.AddSocketDataProvider(&data);
6015
6016 TestCompletionCallback callback;
6017
6018 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6019 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6020
6021 int rv = trans->Start(&request, &callback, BoundNetLog());
6022
6023 EXPECT_EQ(ERR_IO_PENDING, rv);
6024 EXPECT_EQ(OK, callback.WaitForResult());
6025
6026 const HttpResponseInfo* response = trans->GetResponseInfo();
6027 ASSERT_TRUE(response != NULL);
6028 ASSERT_TRUE(response->headers != NULL);
6029 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6030
6031 std::string response_data;
6032 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6033 EXPECT_EQ("hello world", response_data);
6034
6035 EXPECT_FALSE(response->was_fetched_via_spdy);
6036 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576037 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:536038
6039 HttpNetworkTransaction::SetNextProtos("");
6040 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6041}
[email protected]26ef6582010-06-24 02:30:476042
6043TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
6044 // Simulate the SSL handshake completing with an NPN negotiation
6045 // followed by an immediate server closing of the socket.
6046 // Fix crash: http://crbug.com/46369
6047 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6048 HttpNetworkTransaction::SetNextProtos(
6049 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
6050 SessionDependencies session_deps;
6051
6052 HttpRequestInfo request;
6053 request.method = "GET";
6054 request.url = GURL("https://www.google.com/");
6055 request.load_flags = 0;
6056
6057 SSLSocketDataProvider ssl(true, OK);
6058 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6059 ssl.next_proto = "spdy/1";
6060 ssl.was_npn_negotiated = true;
6061 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6062
[email protected]75f30cc22010-06-28 21:41:386063 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0));
[email protected]e7f75092010-07-01 22:39:136064 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:476065
6066 MockRead spdy_reads[] = {
6067 MockRead(false, 0, 0) // Not async - return 0 immediately.
6068 };
6069
6070 scoped_refptr<DelayedSocketData> spdy_data(
6071 new DelayedSocketData(
6072 0, // don't wait in this case, immediate hangup.
6073 spdy_reads, arraysize(spdy_reads),
6074 spdy_writes, arraysize(spdy_writes)));
6075 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6076
6077 TestCompletionCallback callback;
6078
6079 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6080 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6081
6082 int rv = trans->Start(&request, &callback, BoundNetLog());
6083 EXPECT_EQ(ERR_IO_PENDING, rv);
6084 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
6085
6086 HttpNetworkTransaction::SetNextProtos("");
6087 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6088}
[email protected]65d34382010-07-01 18:12:266089
[email protected]89ceba9a2009-03-21 03:46:066090} // namespace net