blob: b4278146878049b73cd3becabe529959f5d366f0 [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]385a4672009-03-11 22:21:2926#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5727#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5228#include "net/http/http_network_session.h"
[email protected]0877e3d2009-10-17 22:29:5729#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5230#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5331#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1132#include "net/proxy/proxy_resolver.h"
33#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4434#include "net/socket/client_socket_factory.h"
35#include "net/socket/socket_test_util.h"
36#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5437#include "net/spdy/spdy_framer.h"
38#include "net/spdy/spdy_session.h"
39#include "net/spdy/spdy_session_pool.h"
40#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5241#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1542#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5243
44//-----------------------------------------------------------------------------
45
[email protected]89ceba9a2009-03-21 03:46:0646namespace net {
47
[email protected]2d731a32010-04-29 01:04:0648class HttpNetworkSessionPeer {
49 public:
50 explicit HttpNetworkSessionPeer(
51 const scoped_refptr<HttpNetworkSession>& session)
52 : session_(session) {}
53
54 void SetTCPSocketPool(const scoped_refptr<TCPClientSocketPool>& pool) {
55 session_->tcp_socket_pool_ = pool;
56 }
57
58 void SetSocketPoolForSOCKSProxy(
59 const HostPortPair& socks_proxy,
60 const scoped_refptr<SOCKSClientSocketPool>& pool) {
61 session_->socks_socket_pool_[socks_proxy] = pool;
62 }
63
64 void SetSocketPoolForHTTPProxy(
65 const HostPortPair& http_proxy,
66 const scoped_refptr<TCPClientSocketPool>& pool) {
67 session_->http_proxy_socket_pool_[http_proxy] = pool;
68 }
69
70 private:
71 const scoped_refptr<HttpNetworkSession> session_;
72
73 DISALLOW_COPY_AND_ASSIGN(HttpNetworkSessionPeer);
74};
75
[email protected]e44de5d2009-06-05 20:12:4576// Helper to manage the lifetimes of the dependencies for a
77// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5978class SessionDependencies {
79 public:
80 // 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()),
86 spdy_session_pool(new SpdySessionPool) {}
[email protected]228ff742009-06-05 01:19:5987
88 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4589 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4290 : host_resolver(new MockHostResolver),
91 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1092 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:5293 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
94 spdy_session_pool(new SpdySessionPool) {}
[email protected]228ff742009-06-05 01:19:5995
[email protected]a2c2fb92009-07-18 07:31:0496 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0997 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4298 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5999 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50100 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a554a8262010-05-20 00:13:52101 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]228ff742009-06-05 01:19:59102};
103
[email protected]1c773ea12009-04-28 19:58:42104ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50105 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48106 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39107 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53108}
109
[email protected]228ff742009-06-05 01:19:59110HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]d13c3272010-02-04 00:24:51111 return new HttpNetworkSession(NULL,
112 session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:09113 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42114 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10115 session_deps->ssl_config_service,
[email protected]a554a8262010-05-20 00:13:52116 session_deps->spdy_session_pool,
[email protected]fa55e192010-02-15 14:25:50117 session_deps->http_auth_handler_factory.get());
[email protected]e8d536192008-10-17 22:21:14118}
119
[email protected]89836e22008-09-25 20:33:42120class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52121 public:
[email protected]2ff8b312010-04-26 22:20:54122 virtual void SetUp() {
123 spdy::SpdyFramer::set_enable_compression_default(false);
124 }
125
[email protected]0e75a732008-10-16 20:36:09126 virtual void TearDown() {
[email protected]2ff8b312010-04-26 22:20:54127 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09128 // Empty the current queue.
129 MessageLoop::current()->RunAllPending();
130 PlatformTest::TearDown();
131 }
132
[email protected]3d2a59b2008-09-26 19:44:25133 protected:
134 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52135
[email protected]ff007e162009-05-23 09:13:15136 struct SimpleGetHelperResult {
137 int rv;
138 std::string status_line;
139 std::string response_data;
140 };
initial.commit586acc5fe2008-07-26 22:42:52141
[email protected]31a2bfe2010-02-09 08:03:39142 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
143 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15144 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52145
[email protected]228ff742009-06-05 01:19:59146 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40147 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43148 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52149
[email protected]ff007e162009-05-23 09:13:15150 HttpRequestInfo request;
151 request.method = "GET";
152 request.url = GURL("http://www.google.com/");
153 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52154
[email protected]31a2bfe2010-02-09 08:03:39155 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59156 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52157
[email protected]ff007e162009-05-23 09:13:15158 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52159
[email protected]169d0012010-05-10 23:20:12160 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
161 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15162 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52163
[email protected]ff007e162009-05-23 09:13:15164 out.rv = callback.WaitForResult();
165 if (out.rv != OK)
166 return out;
167
168 const HttpResponseInfo* response = trans->GetResponseInfo();
169 EXPECT_TRUE(response != NULL);
170
171 EXPECT_TRUE(response->headers != NULL);
172 out.status_line = response->headers->GetStatusLine();
173
174 rv = ReadTransaction(trans.get(), &out.response_data);
175 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39176 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12177 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
178 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39179 ExpectLogContainsSomewhere(
180 log.entries(), pos,
181 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
182 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15183
[email protected]aecfbf22008-10-16 02:02:47184 return out;
[email protected]ff007e162009-05-23 09:13:15185 }
initial.commit586acc5fe2008-07-26 22:42:52186
[email protected]ff007e162009-05-23 09:13:15187 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
188 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52189
[email protected]ff007e162009-05-23 09:13:15190 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15191};
[email protected]231d5a32008-09-13 00:45:27192
[email protected]15a5ccf82008-10-23 19:57:43193// Fill |str| with a long header list that consumes >= |size| bytes.
194void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19195 const char* row =
196 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
197 const int sizeof_row = strlen(row);
198 const int num_rows = static_cast<int>(
199 ceil(static_cast<float>(size) / sizeof_row));
200 const int sizeof_data = num_rows * sizeof_row;
201 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43202 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51203
[email protected]4ddaf2502008-10-23 18:26:19204 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43205 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19206}
207
[email protected]385a4672009-03-11 22:21:29208// Alternative functions that eliminate randomness and dependency on the local
209// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20210void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29211 static const uint8 bytes[] = {
212 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
213 };
214 static size_t current_byte = 0;
215 for (size_t i = 0; i < n; ++i) {
216 output[i] = bytes[current_byte++];
217 current_byte %= arraysize(bytes);
218 }
219}
220
[email protected]fe2bc6a2009-03-23 16:52:20221void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29222 static const uint8 bytes[] = {
223 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
224 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
225 };
226 static size_t current_byte = 0;
227 for (size_t i = 0; i < n; ++i) {
228 output[i] = bytes[current_byte++];
229 current_byte %= arraysize(bytes);
230 }
231}
232
[email protected]fe2bc6a2009-03-23 16:52:20233std::string MockGetHostName() {
234 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29235}
236
[email protected]2d731a32010-04-29 01:04:06237template<typename EmulatedClientSocketPool>
[email protected]a796bcec2010-03-22 17:17:26238class CaptureGroupNameSocketPool : public EmulatedClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31239 public:
[email protected]2d731a32010-04-29 01:04:06240 CaptureGroupNameSocketPool(HttpNetworkSession* session)
[email protected]b89f7e42010-05-20 20:37:00241 : EmulatedClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
[email protected]a554a8262010-05-20 00:13:52242 NULL) {}
[email protected]d80a4322009-08-14 07:07:49243 const std::string last_group_name_received() const {
244 return last_group_name_;
245 }
246
[email protected]684970b2009-08-14 04:54:46247 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49248 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31249 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31250 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46251 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53252 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31253 last_group_name_ = group_name;
254 return ERR_IO_PENDING;
255 }
[email protected]04e5be32009-06-26 20:00:31256 virtual void CancelRequest(const std::string& group_name,
257 const ClientSocketHandle* handle) { }
258 virtual void ReleaseSocket(const std::string& group_name,
259 ClientSocket* socket) {}
260 virtual void CloseIdleSockets() {}
261 virtual HostResolver* GetHostResolver() const {
262 return NULL;
263 }
264 virtual int IdleSocketCount() const {
265 return 0;
266 }
267 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
268 return 0;
269 }
270 virtual LoadState GetLoadState(const std::string& group_name,
271 const ClientSocketHandle* handle) const {
272 return LOAD_STATE_IDLE;
273 }
[email protected]a796bcec2010-03-22 17:17:26274 virtual base::TimeDelta ConnectionTimeout() const {
275 return base::TimeDelta();
276 }
[email protected]d80a4322009-08-14 07:07:49277
278 private:
[email protected]04e5be32009-06-26 20:00:31279 std::string last_group_name_;
280};
281
[email protected]2d731a32010-04-29 01:04:06282typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11283CaptureGroupNameTCPSocketPool;
[email protected]2d731a32010-04-29 01:04:06284typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11285CaptureGroupNameSOCKSSocketPool;
286
[email protected]231d5a32008-09-13 00:45:27287//-----------------------------------------------------------------------------
288
289TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59290 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40291 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43292 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27293}
294
295TEST_F(HttpNetworkTransactionTest, SimpleGET) {
296 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35297 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
298 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42299 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27300 };
[email protected]31a2bfe2010-02-09 08:03:39301 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
302 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42303 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27304 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
305 EXPECT_EQ("hello world", out.response_data);
306}
307
308// Response with no status line.
309TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
310 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35311 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42312 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27313 };
[email protected]31a2bfe2010-02-09 08:03:39314 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
315 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42316 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27317 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
318 EXPECT_EQ("hello world", out.response_data);
319}
320
321// Allow up to 4 bytes of junk to precede status line.
322TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
323 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35324 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42325 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27326 };
[email protected]31a2bfe2010-02-09 08:03:39327 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
328 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42329 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27330 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
331 EXPECT_EQ("DATA", out.response_data);
332}
333
334// Allow up to 4 bytes of junk to precede status line.
335TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
336 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35337 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42338 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27339 };
[email protected]31a2bfe2010-02-09 08:03:39340 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
341 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42342 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27343 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
344 EXPECT_EQ("DATA", out.response_data);
345}
346
347// Beyond 4 bytes of slop and it should fail to find a status line.
348TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
349 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35350 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42351 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27352 };
[email protected]31a2bfe2010-02-09 08:03:39353 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
354 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42355 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25356 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
357 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27358}
359
360// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
361TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
362 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35363 MockRead("\n"),
364 MockRead("\n"),
365 MockRead("Q"),
366 MockRead("J"),
367 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42368 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27369 };
[email protected]31a2bfe2010-02-09 08:03:39370 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
371 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42372 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27373 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
374 EXPECT_EQ("DATA", out.response_data);
375}
376
377// Close the connection before enough bytes to have a status line.
378TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
379 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35380 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42381 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27382 };
[email protected]31a2bfe2010-02-09 08:03:39383 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
384 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42385 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27386 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
387 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52388}
389
[email protected]f9d44aa2008-09-23 23:57:17390// Simulate a 204 response, lacking a Content-Length header, sent over a
391// persistent connection. The response should still terminate since a 204
392// cannot have a response body.
393TEST_F(HttpNetworkTransactionTest, StopsReading204) {
394 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35395 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
396 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42397 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17398 };
[email protected]31a2bfe2010-02-09 08:03:39399 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
400 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42401 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17402 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
403 EXPECT_EQ("", out.response_data);
404}
405
[email protected]0877e3d2009-10-17 22:29:57406// A simple request using chunked encoding with some extra data after.
407// (Like might be seen in a pipelined response.)
408TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
409 MockRead data_reads[] = {
410 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
411 MockRead("5\r\nHello\r\n"),
412 MockRead("1\r\n"),
413 MockRead(" \r\n"),
414 MockRead("5\r\nworld\r\n"),
415 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
416 MockRead(false, OK),
417 };
[email protected]31a2bfe2010-02-09 08:03:39418 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
419 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57420 EXPECT_EQ(OK, out.rv);
421 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
422 EXPECT_EQ("Hello world", out.response_data);
423}
424
[email protected]ef0faf2e72009-03-05 23:27:23425// Do a request using the HEAD method. Verify that we don't try to read the
426// message body (since HEAD has none).
427TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59428 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40429 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43430 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23431
[email protected]1c773ea12009-04-28 19:58:42432 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23433 request.method = "HEAD";
434 request.url = GURL("http://www.google.com/");
435 request.load_flags = 0;
436
437 MockWrite data_writes1[] = {
438 MockWrite("HEAD / HTTP/1.1\r\n"
439 "Host: www.google.com\r\n"
440 "Connection: keep-alive\r\n"
441 "Content-Length: 0\r\n\r\n"),
442 };
443 MockRead data_reads1[] = {
444 MockRead("HTTP/1.1 404 Not Found\r\n"),
445 MockRead("Server: Blah\r\n"),
446 MockRead("Content-Length: 1234\r\n\r\n"),
447
448 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42449 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23450 };
451
[email protected]31a2bfe2010-02-09 08:03:39452 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
453 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59454 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23455
456 TestCompletionCallback callback1;
457
[email protected]5a1d7ca2010-04-28 20:12:27458 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42459 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23460
461 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42462 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23463
[email protected]1c773ea12009-04-28 19:58:42464 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23465 EXPECT_FALSE(response == NULL);
466
467 // Check that the headers got parsed.
468 EXPECT_TRUE(response->headers != NULL);
469 EXPECT_EQ(1234, response->headers->GetContentLength());
470 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
471
472 std::string server_header;
473 void* iter = NULL;
474 bool has_server_header = response->headers->EnumerateHeader(
475 &iter, "Server", &server_header);
476 EXPECT_TRUE(has_server_header);
477 EXPECT_EQ("Blah", server_header);
478
479 // Reading should give EOF right away, since there is no message body
480 // (despite non-zero content-length).
481 std::string response_data;
482 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42483 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23484 EXPECT_EQ("", response_data);
485}
486
initial.commit586acc5fe2008-07-26 22:42:52487TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59488 SessionDependencies session_deps;
489 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52490
491 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35492 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
493 MockRead("hello"),
494 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
495 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42496 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52497 };
[email protected]31a2bfe2010-02-09 08:03:39498 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59499 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52500
501 const char* kExpectedResponseData[] = {
502 "hello", "world"
503 };
504
505 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43506 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52507
[email protected]1c773ea12009-04-28 19:58:42508 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52509 request.method = "GET";
510 request.url = GURL("http://www.google.com/");
511 request.load_flags = 0;
512
513 TestCompletionCallback callback;
514
[email protected]5a1d7ca2010-04-28 20:12:27515 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42516 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52517
518 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42519 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52520
[email protected]1c773ea12009-04-28 19:58:42521 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52522 EXPECT_TRUE(response != NULL);
523
524 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25525 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52526
527 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57528 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42529 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25530 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52531 }
532}
533
534TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59535 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40536 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43537 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52538
[email protected]1c773ea12009-04-28 19:58:42539 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52540 request.method = "POST";
541 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42542 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52543 request.upload_data->AppendBytes("foo", 3);
544 request.load_flags = 0;
545
546 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35547 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
548 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
549 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42550 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52551 };
[email protected]31a2bfe2010-02-09 08:03:39552 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59553 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52554
555 TestCompletionCallback callback;
556
[email protected]5a1d7ca2010-04-28 20:12:27557 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42558 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52559
560 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42561 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52562
[email protected]1c773ea12009-04-28 19:58:42563 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52564 EXPECT_TRUE(response != NULL);
565
566 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25567 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52568
569 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57570 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42571 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25572 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52573}
574
[email protected]3a2d3662009-03-27 03:49:14575// This test is almost the same as Ignores100 above, but the response contains
576// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57577// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14578TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59579 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40580 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43581 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14582
[email protected]1c773ea12009-04-28 19:58:42583 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14584 request.method = "GET";
585 request.url = GURL("http://www.foo.com/");
586 request.load_flags = 0;
587
588 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57589 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
590 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14591 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42592 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14593 };
[email protected]31a2bfe2010-02-09 08:03:39594 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59595 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14596
597 TestCompletionCallback callback;
598
[email protected]5a1d7ca2010-04-28 20:12:27599 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42600 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14601
602 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42603 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14604
[email protected]1c773ea12009-04-28 19:58:42605 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14606 EXPECT_TRUE(response != NULL);
607
608 EXPECT_TRUE(response->headers != NULL);
609 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
610
611 std::string response_data;
612 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42613 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14614 EXPECT_EQ("hello world", response_data);
615}
616
[email protected]ee9410e72010-01-07 01:42:38617TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
618 SessionDependencies session_deps;
619 scoped_ptr<HttpTransaction> trans(
620 new HttpNetworkTransaction(CreateSession(&session_deps)));
621
622 HttpRequestInfo request;
623 request.method = "POST";
624 request.url = GURL("http://www.foo.com/");
625 request.load_flags = 0;
626
627 MockRead data_reads[] = {
628 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
629 MockRead(true, 0),
630 };
[email protected]31a2bfe2010-02-09 08:03:39631 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38632 session_deps.socket_factory.AddSocketDataProvider(&data);
633
634 TestCompletionCallback callback;
635
[email protected]5a1d7ca2010-04-28 20:12:27636 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38637 EXPECT_EQ(ERR_IO_PENDING, rv);
638
639 rv = callback.WaitForResult();
640 EXPECT_EQ(OK, rv);
641
642 std::string response_data;
643 rv = ReadTransaction(trans.get(), &response_data);
644 EXPECT_EQ(OK, rv);
645 EXPECT_EQ("", response_data);
646}
647
648TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
649 SessionDependencies session_deps;
650 scoped_ptr<HttpTransaction> trans(
651 new HttpNetworkTransaction(CreateSession(&session_deps)));
652
653 HttpRequestInfo request;
654 request.method = "POST";
655 request.url = GURL("http://www.foo.com/");
656 request.load_flags = 0;
657
658 MockRead data_reads[] = {
659 MockRead(true, 0),
660 };
[email protected]31a2bfe2010-02-09 08:03:39661 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38662 session_deps.socket_factory.AddSocketDataProvider(&data);
663
664 TestCompletionCallback callback;
665
[email protected]5a1d7ca2010-04-28 20:12:27666 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38667 EXPECT_EQ(ERR_IO_PENDING, rv);
668
669 rv = callback.WaitForResult();
670 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
671}
672
[email protected]3d2a59b2008-09-26 19:44:25673// read_failure specifies a read failure that should cause the network
674// transaction to resend the request.
675void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
676 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59677 SessionDependencies session_deps;
678 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52679
[email protected]1c773ea12009-04-28 19:58:42680 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52681 request.method = "GET";
682 request.url = GURL("http://www.foo.com/");
683 request.load_flags = 0;
684
685 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35686 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
687 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25688 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52689 };
[email protected]31a2bfe2010-02-09 08:03:39690 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59691 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52692
693 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35694 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
695 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42696 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52697 };
[email protected]31a2bfe2010-02-09 08:03:39698 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59699 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52700
701 const char* kExpectedResponseData[] = {
702 "hello", "world"
703 };
704
705 for (int i = 0; i < 2; ++i) {
706 TestCompletionCallback callback;
707
[email protected]5695b8c2009-09-30 21:36:43708 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52709
[email protected]5a1d7ca2010-04-28 20:12:27710 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42711 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52712
713 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42714 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52715
[email protected]1c773ea12009-04-28 19:58:42716 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52717 EXPECT_TRUE(response != NULL);
718
719 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25720 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52721
722 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57723 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42724 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25725 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52726 }
727}
[email protected]3d2a59b2008-09-26 19:44:25728
729TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42730 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25731 KeepAliveConnectionResendRequestTest(read_failure);
732}
733
734TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42735 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25736 KeepAliveConnectionResendRequestTest(read_failure);
737}
738
739TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59740 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40741 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43742 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25743
[email protected]1c773ea12009-04-28 19:58:42744 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25745 request.method = "GET";
746 request.url = GURL("http://www.google.com/");
747 request.load_flags = 0;
748
749 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42750 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35751 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
752 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42753 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25754 };
[email protected]31a2bfe2010-02-09 08:03:39755 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59756 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25757
758 TestCompletionCallback callback;
759
[email protected]5a1d7ca2010-04-28 20:12:27760 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42761 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25762
763 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42764 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25765
[email protected]1c773ea12009-04-28 19:58:42766 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25767 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25768}
769
770// What do various browsers do when the server closes a non-keepalive
771// connection without sending any response header or body?
772//
773// IE7: error page
774// Safari 3.1.2 (Windows): error page
775// Firefox 3.0.1: blank page
776// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42777// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
778// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25779TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
780 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42781 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35782 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
783 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42784 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25785 };
[email protected]31a2bfe2010-02-09 08:03:39786 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
787 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42788 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25789}
[email protected]038e9a32008-10-08 22:40:16790
791// Test the request-challenge-retry sequence for basic auth.
792// (basic auth is the easiest to mock, because it has no randomness).
793TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59794 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40795 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43796 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16797
[email protected]1c773ea12009-04-28 19:58:42798 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16799 request.method = "GET";
800 request.url = GURL("http://www.google.com/");
801 request.load_flags = 0;
802
[email protected]f9ee6b52008-11-08 06:46:23803 MockWrite data_writes1[] = {
804 MockWrite("GET / HTTP/1.1\r\n"
805 "Host: www.google.com\r\n"
806 "Connection: keep-alive\r\n\r\n"),
807 };
808
[email protected]038e9a32008-10-08 22:40:16809 MockRead data_reads1[] = {
810 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
811 // Give a couple authenticate options (only the middle one is actually
812 // supported).
[email protected]22927ad2009-09-21 19:56:19813 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16814 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
815 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
816 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
817 // Large content-length -- won't matter, as connection will be reset.
818 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42819 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16820 };
821
822 // After calling trans->RestartWithAuth(), this is the request we should
823 // be issuing -- the final header line contains the credentials.
824 MockWrite data_writes2[] = {
825 MockWrite("GET / HTTP/1.1\r\n"
826 "Host: www.google.com\r\n"
827 "Connection: keep-alive\r\n"
828 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
829 };
830
831 // Lastly, the server responds with the actual content.
832 MockRead data_reads2[] = {
833 MockRead("HTTP/1.0 200 OK\r\n"),
834 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
835 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42836 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16837 };
838
[email protected]31a2bfe2010-02-09 08:03:39839 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
840 data_writes1, arraysize(data_writes1));
841 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
842 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59843 session_deps.socket_factory.AddSocketDataProvider(&data1);
844 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16845
846 TestCompletionCallback callback1;
847
[email protected]5a1d7ca2010-04-28 20:12:27848 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42849 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16850
851 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42852 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16853
[email protected]1c773ea12009-04-28 19:58:42854 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16855 EXPECT_FALSE(response == NULL);
856
857 // The password prompt info should have been set in response->auth_challenge.
858 EXPECT_FALSE(response->auth_challenge.get() == NULL);
859
[email protected]71e4573a2009-05-21 22:03:00860 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16861 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
862 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
863
864 TestCompletionCallback callback2;
865
866 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42867 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16868
869 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42870 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16871
872 response = trans->GetResponseInfo();
873 EXPECT_FALSE(response == NULL);
874 EXPECT_TRUE(response->auth_challenge.get() == NULL);
875 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16876}
877
[email protected]861fcd52009-08-26 02:33:46878TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
879 SessionDependencies session_deps;
880 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43881 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46882
883 HttpRequestInfo request;
884 request.method = "GET";
885 request.url = GURL("http://www.google.com/");
886 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
887
888 MockWrite data_writes[] = {
889 MockWrite("GET / HTTP/1.1\r\n"
890 "Host: www.google.com\r\n"
891 "Connection: keep-alive\r\n\r\n"),
892 };
893
894 MockRead data_reads[] = {
895 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
896 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
897 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
898 // Large content-length -- won't matter, as connection will be reset.
899 MockRead("Content-Length: 10000\r\n\r\n"),
900 MockRead(false, ERR_FAILED),
901 };
902
[email protected]31a2bfe2010-02-09 08:03:39903 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
904 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59905 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46906 TestCompletionCallback callback;
907
[email protected]5a1d7ca2010-04-28 20:12:27908 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:46909 EXPECT_EQ(ERR_IO_PENDING, rv);
910
911 rv = callback.WaitForResult();
912 EXPECT_EQ(0, rv);
913
914 const HttpResponseInfo* response = trans->GetResponseInfo();
915 ASSERT_FALSE(response == NULL);
916 EXPECT_TRUE(response->auth_challenge.get() == NULL);
917}
918
[email protected]2d2697f92009-02-18 21:00:32919// Test the request-challenge-retry sequence for basic auth, over a keep-alive
920// connection.
921TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59922 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40923 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43924 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32925
[email protected]1c773ea12009-04-28 19:58:42926 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32927 request.method = "GET";
928 request.url = GURL("http://www.google.com/");
929 request.load_flags = 0;
930
931 MockWrite data_writes1[] = {
932 MockWrite("GET / HTTP/1.1\r\n"
933 "Host: www.google.com\r\n"
934 "Connection: keep-alive\r\n\r\n"),
935
936 // After calling trans->RestartWithAuth(), this is the request we should
937 // be issuing -- the final header line contains the credentials.
938 MockWrite("GET / HTTP/1.1\r\n"
939 "Host: www.google.com\r\n"
940 "Connection: keep-alive\r\n"
941 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
942 };
943
944 MockRead data_reads1[] = {
945 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
946 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
947 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
948 MockRead("Content-Length: 14\r\n\r\n"),
949 MockRead("Unauthorized\r\n"),
950
951 // Lastly, the server responds with the actual content.
952 MockRead("HTTP/1.1 200 OK\r\n"),
953 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
954 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42955 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32956 };
957
[email protected]31a2bfe2010-02-09 08:03:39958 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
959 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59960 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32961
962 TestCompletionCallback callback1;
963
[email protected]5a1d7ca2010-04-28 20:12:27964 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42965 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32966
967 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42968 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32969
[email protected]1c773ea12009-04-28 19:58:42970 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32971 EXPECT_FALSE(response == NULL);
972
973 // The password prompt info should have been set in response->auth_challenge.
974 EXPECT_FALSE(response->auth_challenge.get() == NULL);
975
[email protected]71e4573a2009-05-21 22:03:00976 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32977 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
978 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
979
980 TestCompletionCallback callback2;
981
982 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42983 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32984
985 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42986 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32987
988 response = trans->GetResponseInfo();
989 EXPECT_FALSE(response == NULL);
990 EXPECT_TRUE(response->auth_challenge.get() == NULL);
991 EXPECT_EQ(100, response->headers->GetContentLength());
992}
993
994// Test the request-challenge-retry sequence for basic auth, over a keep-alive
995// connection and with no response body to drain.
996TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59997 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40998 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43999 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321000
[email protected]1c773ea12009-04-28 19:58:421001 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321002 request.method = "GET";
1003 request.url = GURL("http://www.google.com/");
1004 request.load_flags = 0;
1005
1006 MockWrite data_writes1[] = {
1007 MockWrite("GET / HTTP/1.1\r\n"
1008 "Host: www.google.com\r\n"
1009 "Connection: keep-alive\r\n\r\n"),
1010
1011 // After calling trans->RestartWithAuth(), this is the request we should
1012 // be issuing -- the final header line contains the credentials.
1013 MockWrite("GET / HTTP/1.1\r\n"
1014 "Host: www.google.com\r\n"
1015 "Connection: keep-alive\r\n"
1016 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1017 };
1018
[email protected]2d2697f92009-02-18 21:00:321019 MockRead data_reads1[] = {
1020 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1021 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311022 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321023
1024 // Lastly, the server responds with the actual content.
1025 MockRead("HTTP/1.1 200 OK\r\n"),
1026 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1027 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421028 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321029 };
1030
[email protected]31a2bfe2010-02-09 08:03:391031 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1032 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591033 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321034
1035 TestCompletionCallback callback1;
1036
[email protected]5a1d7ca2010-04-28 20:12:271037 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421038 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321039
1040 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421041 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321042
[email protected]1c773ea12009-04-28 19:58:421043 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321044 EXPECT_FALSE(response == NULL);
1045
1046 // The password prompt info should have been set in response->auth_challenge.
1047 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1048
[email protected]71e4573a2009-05-21 22:03:001049 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321050 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1051 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1052
1053 TestCompletionCallback callback2;
1054
1055 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421056 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321057
1058 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421059 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321060
1061 response = trans->GetResponseInfo();
1062 EXPECT_FALSE(response == NULL);
1063 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1064 EXPECT_EQ(100, response->headers->GetContentLength());
1065}
1066
1067// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1068// connection and with a large response body to drain.
1069TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591070 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401071 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431072 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321073
[email protected]1c773ea12009-04-28 19:58:421074 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321075 request.method = "GET";
1076 request.url = GURL("http://www.google.com/");
1077 request.load_flags = 0;
1078
1079 MockWrite data_writes1[] = {
1080 MockWrite("GET / HTTP/1.1\r\n"
1081 "Host: www.google.com\r\n"
1082 "Connection: keep-alive\r\n\r\n"),
1083
1084 // After calling trans->RestartWithAuth(), this is the request we should
1085 // be issuing -- the final header line contains the credentials.
1086 MockWrite("GET / HTTP/1.1\r\n"
1087 "Host: www.google.com\r\n"
1088 "Connection: keep-alive\r\n"
1089 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1090 };
1091
1092 // Respond with 5 kb of response body.
1093 std::string large_body_string("Unauthorized");
1094 large_body_string.append(5 * 1024, ' ');
1095 large_body_string.append("\r\n");
1096
1097 MockRead data_reads1[] = {
1098 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1099 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1100 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1101 // 5134 = 12 + 5 * 1024 + 2
1102 MockRead("Content-Length: 5134\r\n\r\n"),
1103 MockRead(true, large_body_string.data(), large_body_string.size()),
1104
1105 // Lastly, the server responds with the actual content.
1106 MockRead("HTTP/1.1 200 OK\r\n"),
1107 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1108 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421109 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321110 };
1111
[email protected]31a2bfe2010-02-09 08:03:391112 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1113 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591114 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321115
1116 TestCompletionCallback callback1;
1117
[email protected]5a1d7ca2010-04-28 20:12:271118 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421119 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321120
1121 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421122 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321123
[email protected]1c773ea12009-04-28 19:58:421124 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321125 EXPECT_FALSE(response == NULL);
1126
1127 // The password prompt info should have been set in response->auth_challenge.
1128 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1129
[email protected]71e4573a2009-05-21 22:03:001130 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321131 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1132 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1133
1134 TestCompletionCallback callback2;
1135
1136 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421137 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321138
1139 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421140 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321141
1142 response = trans->GetResponseInfo();
1143 EXPECT_FALSE(response == NULL);
1144 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1145 EXPECT_EQ(100, response->headers->GetContentLength());
1146}
1147
1148// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311149// connection, but the server gets impatient and closes the connection.
1150TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1151 SessionDependencies session_deps;
1152 scoped_ptr<HttpTransaction> trans(
1153 new HttpNetworkTransaction(CreateSession(&session_deps)));
1154
1155 HttpRequestInfo request;
1156 request.method = "GET";
1157 request.url = GURL("http://www.google.com/");
1158 request.load_flags = 0;
1159
1160 MockWrite data_writes1[] = {
1161 MockWrite("GET / HTTP/1.1\r\n"
1162 "Host: www.google.com\r\n"
1163 "Connection: keep-alive\r\n\r\n"),
1164 // This simulates the seemingly successful write to a closed connection
1165 // if the bug is not fixed.
1166 MockWrite("GET / HTTP/1.1\r\n"
1167 "Host: www.google.com\r\n"
1168 "Connection: keep-alive\r\n"
1169 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1170 };
1171
1172 MockRead data_reads1[] = {
1173 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1174 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1175 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1176 MockRead("Content-Length: 14\r\n\r\n"),
1177 // Tell MockTCPClientSocket to simulate the server closing the connection.
1178 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1179 MockRead("Unauthorized\r\n"),
1180 MockRead(false, OK), // The server closes the connection.
1181 };
1182
1183 // After calling trans->RestartWithAuth(), this is the request we should
1184 // be issuing -- the final header line contains the credentials.
1185 MockWrite data_writes2[] = {
1186 MockWrite("GET / HTTP/1.1\r\n"
1187 "Host: www.google.com\r\n"
1188 "Connection: keep-alive\r\n"
1189 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1190 };
1191
1192 // Lastly, the server responds with the actual content.
1193 MockRead data_reads2[] = {
1194 MockRead("HTTP/1.1 200 OK\r\n"),
1195 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1196 MockRead("Content-Length: 100\r\n\r\n"),
1197 MockRead(false, OK),
1198 };
1199
[email protected]31a2bfe2010-02-09 08:03:391200 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1201 data_writes1, arraysize(data_writes1));
1202 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1203 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311204 session_deps.socket_factory.AddSocketDataProvider(&data1);
1205 session_deps.socket_factory.AddSocketDataProvider(&data2);
1206
1207 TestCompletionCallback callback1;
1208
[email protected]5a1d7ca2010-04-28 20:12:271209 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311210 EXPECT_EQ(ERR_IO_PENDING, rv);
1211
1212 rv = callback1.WaitForResult();
1213 EXPECT_EQ(OK, rv);
1214
1215 const HttpResponseInfo* response = trans->GetResponseInfo();
1216 EXPECT_FALSE(response == NULL);
1217
1218 // The password prompt info should have been set in response->auth_challenge.
1219 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1220
1221 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1222 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1223 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1224
1225 TestCompletionCallback callback2;
1226
1227 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1228 EXPECT_EQ(ERR_IO_PENDING, rv);
1229
1230 rv = callback2.WaitForResult();
1231 EXPECT_EQ(OK, rv);
1232
1233 response = trans->GetResponseInfo();
1234 ASSERT_FALSE(response == NULL);
1235 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1236 EXPECT_EQ(100, response->headers->GetContentLength());
1237}
1238
1239// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321240// proxy connection, when setting up an SSL tunnel.
1241TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1242 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591243 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1244 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321245
[email protected]5695b8c2009-09-30 21:36:431246 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321247
[email protected]1c773ea12009-04-28 19:58:421248 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321249 request.method = "GET";
1250 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461251 // Ensure that proxy authentication is attempted even
1252 // when the no authentication data flag is set.
1253 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321254
1255 // Since we have proxy, should try to establish tunnel.
1256 MockWrite data_writes1[] = {
1257 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451258 "Host: www.google.com\r\n"
1259 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321260
1261 // After calling trans->RestartWithAuth(), this is the request we should
1262 // be issuing -- the final header line contains the credentials.
1263 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1264 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451265 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321266 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1267 };
1268
1269 // The proxy responds to the connect with a 407, using a persistent
1270 // connection.
1271 MockRead data_reads1[] = {
1272 // No credentials.
1273 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1274 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1275 MockRead("Content-Length: 10\r\n\r\n"),
1276 MockRead("0123456789"),
1277
1278 // Wrong credentials (wrong password).
1279 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1280 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1281 MockRead("Content-Length: 10\r\n\r\n"),
1282 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421283 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321284 };
1285
[email protected]31a2bfe2010-02-09 08:03:391286 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1287 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591288 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321289
1290 TestCompletionCallback callback1;
1291
[email protected]dbb83db2010-05-11 18:13:391292 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1293 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421294 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321295
1296 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421297 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391298 size_t pos = ExpectLogContainsSomewhere(
1299 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1300 NetLog::PHASE_NONE);
1301 ExpectLogContainsSomewhere(
1302 log.entries(), pos,
1303 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1304 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321305
[email protected]1c773ea12009-04-28 19:58:421306 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321307 EXPECT_FALSE(response == NULL);
1308
1309 EXPECT_TRUE(response->headers->IsKeepAlive());
1310 EXPECT_EQ(407, response->headers->response_code());
1311 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421312 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321313
1314 // The password prompt info should have been set in response->auth_challenge.
1315 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1316
[email protected]71e4573a2009-05-21 22:03:001317 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321318 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1319 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1320
1321 TestCompletionCallback callback2;
1322
1323 // Wrong password (should be "bar").
1324 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421325 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321326
1327 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421328 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321329
1330 response = trans->GetResponseInfo();
1331 EXPECT_FALSE(response == NULL);
1332
1333 EXPECT_TRUE(response->headers->IsKeepAlive());
1334 EXPECT_EQ(407, response->headers->response_code());
1335 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421336 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321337
1338 // The password prompt info should have been set in response->auth_challenge.
1339 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1340
[email protected]71e4573a2009-05-21 22:03:001341 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321342 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1343 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1344}
1345
[email protected]a8e9b162009-03-12 00:06:441346// Test that we don't read the response body when we fail to establish a tunnel,
1347// even if the user cancels the proxy's auth attempt.
1348TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1349 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591350 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441351
[email protected]e44de5d2009-06-05 20:12:451352 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441353
[email protected]5695b8c2009-09-30 21:36:431354 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441355
[email protected]1c773ea12009-04-28 19:58:421356 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441357 request.method = "GET";
1358 request.url = GURL("https://www.google.com/");
1359 request.load_flags = 0;
1360
1361 // Since we have proxy, should try to establish tunnel.
1362 MockWrite data_writes[] = {
1363 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451364 "Host: www.google.com\r\n"
1365 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441366 };
1367
1368 // The proxy responds to the connect with a 407.
1369 MockRead data_reads[] = {
1370 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1371 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1372 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421373 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441374 };
1375
[email protected]31a2bfe2010-02-09 08:03:391376 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1377 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591378 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441379
1380 TestCompletionCallback callback;
1381
[email protected]5a1d7ca2010-04-28 20:12:271382 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421383 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441384
1385 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421386 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441387
[email protected]1c773ea12009-04-28 19:58:421388 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441389 EXPECT_FALSE(response == NULL);
1390
1391 EXPECT_TRUE(response->headers->IsKeepAlive());
1392 EXPECT_EQ(407, response->headers->response_code());
1393 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421394 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441395
1396 std::string response_data;
1397 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421398 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441399}
1400
[email protected]8fdbcd22010-05-05 02:54:521401// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1402// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1403TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1404 // We are using a DIRECT connection (i.e. no proxy) for this session.
1405 SessionDependencies session_deps;
1406 scoped_ptr<HttpTransaction> trans(
1407 new HttpNetworkTransaction(CreateSession(&session_deps)));
1408
1409 HttpRequestInfo request;
1410 request.method = "GET";
1411 request.url = GURL("http://www.google.com/");
1412 request.load_flags = 0;
1413
1414 MockWrite data_writes1[] = {
1415 MockWrite("GET / HTTP/1.1\r\n"
1416 "Host: www.google.com\r\n"
1417 "Connection: keep-alive\r\n\r\n"),
1418 };
1419
1420 MockRead data_reads1[] = {
1421 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1422 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1423 // Large content-length -- won't matter, as connection will be reset.
1424 MockRead("Content-Length: 10000\r\n\r\n"),
1425 MockRead(false, ERR_FAILED),
1426 };
1427
1428 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1429 data_writes1, arraysize(data_writes1));
1430 session_deps.socket_factory.AddSocketDataProvider(&data1);
1431
1432 TestCompletionCallback callback;
1433
1434 int rv = trans->Start(&request, &callback, BoundNetLog());
1435 EXPECT_EQ(ERR_IO_PENDING, rv);
1436
1437 rv = callback.WaitForResult();
1438 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1439}
1440
[email protected]ff007e162009-05-23 09:13:151441void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081442 const MockRead& status, int expected_status) {
1443 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591444 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081445
[email protected]228ff742009-06-05 01:19:591446 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081447
[email protected]5695b8c2009-09-30 21:36:431448 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081449
[email protected]1c773ea12009-04-28 19:58:421450 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081451 request.method = "GET";
1452 request.url = GURL("https://www.google.com/");
1453 request.load_flags = 0;
1454
1455 // Since we have proxy, should try to establish tunnel.
1456 MockWrite data_writes[] = {
1457 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451458 "Host: www.google.com\r\n"
1459 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081460 };
1461
1462 MockRead data_reads[] = {
1463 status,
1464 MockRead("Content-Length: 10\r\n\r\n"),
1465 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421466 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081467 };
1468
[email protected]31a2bfe2010-02-09 08:03:391469 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1470 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591471 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081472
1473 TestCompletionCallback callback;
1474
[email protected]5a1d7ca2010-04-28 20:12:271475 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421476 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081477
1478 rv = callback.WaitForResult();
1479 EXPECT_EQ(expected_status, rv);
1480}
1481
[email protected]ff007e162009-05-23 09:13:151482void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081483 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421484 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081485}
1486
1487TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1488 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1489}
1490
1491TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1492 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1493}
1494
1495TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1496 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1497}
1498
1499TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1500 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1501}
1502
1503TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1504 ConnectStatusHelper(
1505 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1506}
1507
1508TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1509 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1510}
1511
1512TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1513 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1514}
1515
1516TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1517 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1518}
1519
1520TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1521 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1522}
1523
1524TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1525 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1526}
1527
1528TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1529 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1530}
1531
1532TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1533 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1534}
1535
1536TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1537 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1538}
1539
1540TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1541 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1542}
1543
1544TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1545 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1546}
1547
1548TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1549 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1550}
1551
1552TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1553 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1554}
1555
1556TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1557 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1558}
1559
1560TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1561 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1562}
1563
1564TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1565 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1566}
1567
1568TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1569 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1570}
1571
1572TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1573 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1574}
1575
1576TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1577 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1578}
1579
1580TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1581 ConnectStatusHelperWithExpectedStatus(
1582 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421583 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081584}
1585
1586TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1587 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1588}
1589
1590TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1591 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1592}
1593
1594TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1595 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1596}
1597
1598TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1599 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1600}
1601
1602TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1603 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1604}
1605
1606TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1607 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1608}
1609
1610TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1611 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1612}
1613
1614TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1615 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1616}
1617
1618TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1619 ConnectStatusHelper(
1620 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1621}
1622
1623TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1624 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1625}
1626
1627TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1628 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1629}
1630
1631TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1632 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1633}
1634
1635TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1636 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1637}
1638
1639TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1640 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1641}
1642
1643TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1644 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1645}
1646
1647TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1648 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1649}
1650
[email protected]038e9a32008-10-08 22:40:161651// Test the flow when both the proxy server AND origin server require
1652// authentication. Again, this uses basic auth for both since that is
1653// the simplest to mock.
1654TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591655 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011656
[email protected]038e9a32008-10-08 22:40:161657 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421658 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431659 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161660
[email protected]1c773ea12009-04-28 19:58:421661 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161662 request.method = "GET";
1663 request.url = GURL("http://www.google.com/");
1664 request.load_flags = 0;
1665
[email protected]f9ee6b52008-11-08 06:46:231666 MockWrite data_writes1[] = {
1667 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1668 "Host: www.google.com\r\n"
1669 "Proxy-Connection: keep-alive\r\n\r\n"),
1670 };
1671
[email protected]038e9a32008-10-08 22:40:161672 MockRead data_reads1[] = {
1673 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1674 // Give a couple authenticate options (only the middle one is actually
1675 // supported).
[email protected]22927ad2009-09-21 19:56:191676 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161677 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1678 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1679 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1680 // Large content-length -- won't matter, as connection will be reset.
1681 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421682 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161683 };
1684
1685 // After calling trans->RestartWithAuth() the first time, this is the
1686 // request we should be issuing -- the final header line contains the
1687 // proxy's credentials.
1688 MockWrite data_writes2[] = {
1689 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1690 "Host: www.google.com\r\n"
1691 "Proxy-Connection: keep-alive\r\n"
1692 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1693 };
1694
1695 // Now the proxy server lets the request pass through to origin server.
1696 // The origin server responds with a 401.
1697 MockRead data_reads2[] = {
1698 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1699 // Note: We are using the same realm-name as the proxy server. This is
1700 // completely valid, as realms are unique across hosts.
1701 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1702 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1703 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421704 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161705 };
1706
1707 // After calling trans->RestartWithAuth() the second time, we should send
1708 // the credentials for both the proxy and origin server.
1709 MockWrite data_writes3[] = {
1710 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1711 "Host: www.google.com\r\n"
1712 "Proxy-Connection: keep-alive\r\n"
1713 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1714 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1715 };
1716
1717 // Lastly we get the desired content.
1718 MockRead data_reads3[] = {
1719 MockRead("HTTP/1.0 200 OK\r\n"),
1720 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1721 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421722 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161723 };
1724
[email protected]31a2bfe2010-02-09 08:03:391725 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1726 data_writes1, arraysize(data_writes1));
1727 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1728 data_writes2, arraysize(data_writes2));
1729 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1730 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591731 session_deps.socket_factory.AddSocketDataProvider(&data1);
1732 session_deps.socket_factory.AddSocketDataProvider(&data2);
1733 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161734
1735 TestCompletionCallback callback1;
1736
[email protected]5a1d7ca2010-04-28 20:12:271737 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421738 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161739
1740 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421741 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161742
[email protected]1c773ea12009-04-28 19:58:421743 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161744 EXPECT_FALSE(response == NULL);
1745
1746 // The password prompt info should have been set in response->auth_challenge.
1747 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1748
[email protected]71e4573a2009-05-21 22:03:001749 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161750 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1751 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1752
1753 TestCompletionCallback callback2;
1754
1755 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421756 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161757
1758 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421759 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161760
1761 response = trans->GetResponseInfo();
1762 EXPECT_FALSE(response == NULL);
1763 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1764
[email protected]71e4573a2009-05-21 22:03:001765 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161766 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1767 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1768
1769 TestCompletionCallback callback3;
1770
1771 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421772 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161773
1774 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421775 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161776
1777 response = trans->GetResponseInfo();
1778 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1779 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161780}
[email protected]4ddaf2502008-10-23 18:26:191781
[email protected]ea9dc9a2009-09-05 00:43:321782// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1783// can't hook into its internals to cause it to generate predictable NTLM
1784// authorization headers.
1785#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291786// The NTLM authentication unit tests were generated by capturing the HTTP
1787// requests and responses using Fiddler 2 and inspecting the generated random
1788// bytes in the debugger.
1789
1790// Enter the correct password and authenticate successfully.
1791TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421792 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:111793 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591794 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401795 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431796 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241797
[email protected]1c773ea12009-04-28 19:58:421798 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241799 request.method = "GET";
1800 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1801 request.load_flags = 0;
1802
1803 MockWrite data_writes1[] = {
1804 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1805 "Host: 172.22.68.17\r\n"
1806 "Connection: keep-alive\r\n\r\n"),
1807 };
1808
1809 MockRead data_reads1[] = {
1810 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1811 // Negotiate and NTLM are often requested together. We only support NTLM.
1812 MockRead("WWW-Authenticate: Negotiate\r\n"),
1813 MockRead("WWW-Authenticate: NTLM\r\n"),
1814 MockRead("Connection: close\r\n"),
1815 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361816 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241817 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421818 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241819 };
1820
1821 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221822 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241823 // request we should be issuing -- the final header line contains a Type
1824 // 1 message.
1825 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1826 "Host: 172.22.68.17\r\n"
1827 "Connection: keep-alive\r\n"
1828 "Authorization: NTLM "
1829 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1830
1831 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1832 // (the credentials for the origin server). The second request continues
1833 // on the same connection.
1834 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1835 "Host: 172.22.68.17\r\n"
1836 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291837 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1838 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1839 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1840 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1841 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241842 };
1843
1844 MockRead data_reads2[] = {
1845 // The origin server responds with a Type 2 message.
1846 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1847 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291848 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241849 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1850 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1851 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1852 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1853 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1854 "BtAAAAAAA=\r\n"),
1855 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361856 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241857 MockRead("You are not authorized to view this page\r\n"),
1858
1859 // Lastly we get the desired content.
1860 MockRead("HTTP/1.1 200 OK\r\n"),
1861 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1862 MockRead("Content-Length: 13\r\n\r\n"),
1863 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421864 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241865 };
1866
[email protected]31a2bfe2010-02-09 08:03:391867 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1868 data_writes1, arraysize(data_writes1));
1869 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1870 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591871 session_deps.socket_factory.AddSocketDataProvider(&data1);
1872 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241873
1874 TestCompletionCallback callback1;
1875
[email protected]5a1d7ca2010-04-28 20:12:271876 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421877 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241878
1879 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421880 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241881
[email protected]0757e7702009-03-27 04:00:221882 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1883 TestCompletionCallback callback2;
1884 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421885 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221886 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421887 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221888 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1889
[email protected]1c773ea12009-04-28 19:58:421890 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241891 EXPECT_FALSE(response == NULL);
1892
1893 // The password prompt info should have been set in response->auth_challenge.
1894 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1895
[email protected]71e4573a2009-05-21 22:03:001896 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241897 EXPECT_EQ(L"", response->auth_challenge->realm);
1898 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1899
[email protected]0757e7702009-03-27 04:00:221900 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241901
[email protected]0757e7702009-03-27 04:00:221902 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421903 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241904
[email protected]0757e7702009-03-27 04:00:221905 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421906 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241907
1908 response = trans->GetResponseInfo();
1909 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1910 EXPECT_EQ(13, response->headers->GetContentLength());
1911}
1912
[email protected]385a4672009-03-11 22:21:291913// Enter a wrong password, and then the correct one.
1914TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421915 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:111916 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591917 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401918 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431919 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291920
[email protected]1c773ea12009-04-28 19:58:421921 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291922 request.method = "GET";
1923 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1924 request.load_flags = 0;
1925
1926 MockWrite data_writes1[] = {
1927 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1928 "Host: 172.22.68.17\r\n"
1929 "Connection: keep-alive\r\n\r\n"),
1930 };
1931
1932 MockRead data_reads1[] = {
1933 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1934 // Negotiate and NTLM are often requested together. We only support NTLM.
1935 MockRead("WWW-Authenticate: Negotiate\r\n"),
1936 MockRead("WWW-Authenticate: NTLM\r\n"),
1937 MockRead("Connection: close\r\n"),
1938 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361939 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291940 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421941 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291942 };
1943
1944 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221945 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291946 // request we should be issuing -- the final header line contains a Type
1947 // 1 message.
1948 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1949 "Host: 172.22.68.17\r\n"
1950 "Connection: keep-alive\r\n"
1951 "Authorization: NTLM "
1952 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1953
1954 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1955 // (the credentials for the origin server). The second request continues
1956 // on the same connection.
1957 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1958 "Host: 172.22.68.17\r\n"
1959 "Connection: keep-alive\r\n"
1960 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1961 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1962 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1963 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1964 "4Ww7b7E=\r\n\r\n"),
1965 };
1966
1967 MockRead data_reads2[] = {
1968 // The origin server responds with a Type 2 message.
1969 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1970 MockRead("WWW-Authenticate: NTLM "
1971 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1972 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1973 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1974 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1975 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1976 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1977 "BtAAAAAAA=\r\n"),
1978 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361979 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291980 MockRead("You are not authorized to view this page\r\n"),
1981
1982 // Wrong password.
1983 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1984 MockRead("WWW-Authenticate: Negotiate\r\n"),
1985 MockRead("WWW-Authenticate: NTLM\r\n"),
1986 MockRead("Connection: close\r\n"),
1987 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361988 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291989 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421990 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291991 };
1992
1993 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221994 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291995 // request we should be issuing -- the final header line contains a Type
1996 // 1 message.
1997 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1998 "Host: 172.22.68.17\r\n"
1999 "Connection: keep-alive\r\n"
2000 "Authorization: NTLM "
2001 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2002
2003 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2004 // (the credentials for the origin server). The second request continues
2005 // on the same connection.
2006 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2007 "Host: 172.22.68.17\r\n"
2008 "Connection: keep-alive\r\n"
2009 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2010 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2011 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2012 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2013 "+4MUm7c=\r\n\r\n"),
2014 };
2015
2016 MockRead data_reads3[] = {
2017 // The origin server responds with a Type 2 message.
2018 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2019 MockRead("WWW-Authenticate: NTLM "
2020 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2021 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2022 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2023 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2024 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2025 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2026 "BtAAAAAAA=\r\n"),
2027 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362028 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292029 MockRead("You are not authorized to view this page\r\n"),
2030
2031 // Lastly we get the desired content.
2032 MockRead("HTTP/1.1 200 OK\r\n"),
2033 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2034 MockRead("Content-Length: 13\r\n\r\n"),
2035 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422036 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292037 };
2038
[email protected]31a2bfe2010-02-09 08:03:392039 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2040 data_writes1, arraysize(data_writes1));
2041 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2042 data_writes2, arraysize(data_writes2));
2043 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2044 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592045 session_deps.socket_factory.AddSocketDataProvider(&data1);
2046 session_deps.socket_factory.AddSocketDataProvider(&data2);
2047 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292048
2049 TestCompletionCallback callback1;
2050
[email protected]5a1d7ca2010-04-28 20:12:272051 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422052 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292053
2054 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422055 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292056
[email protected]0757e7702009-03-27 04:00:222057 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292058 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:222059 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422060 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292061 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422062 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222063 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292064
[email protected]1c773ea12009-04-28 19:58:422065 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292066 EXPECT_FALSE(response == NULL);
2067
2068 // The password prompt info should have been set in response->auth_challenge.
2069 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2070
[email protected]71e4573a2009-05-21 22:03:002071 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292072 EXPECT_EQ(L"", response->auth_challenge->realm);
2073 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2074
2075 TestCompletionCallback callback3;
2076
[email protected]0757e7702009-03-27 04:00:222077 // Enter the wrong password.
2078 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:422079 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292080
2081 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422082 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292083
[email protected]0757e7702009-03-27 04:00:222084 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2085 TestCompletionCallback callback4;
2086 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422087 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222088 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422089 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222090 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2091
2092 response = trans->GetResponseInfo();
2093 EXPECT_FALSE(response == NULL);
2094
2095 // The password prompt info should have been set in response->auth_challenge.
2096 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2097
[email protected]71e4573a2009-05-21 22:03:002098 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222099 EXPECT_EQ(L"", response->auth_challenge->realm);
2100 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2101
2102 TestCompletionCallback callback5;
2103
2104 // Now enter the right password.
2105 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422106 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222107
2108 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422109 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222110
[email protected]385a4672009-03-11 22:21:292111 response = trans->GetResponseInfo();
2112 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2113 EXPECT_EQ(13, response->headers->GetContentLength());
2114}
[email protected]ea9dc9a2009-09-05 00:43:322115#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292116
[email protected]4ddaf2502008-10-23 18:26:192117// Test reading a server response which has only headers, and no body.
2118// After some maximum number of bytes is consumed, the transaction should
2119// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2120TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592121 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402122 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432123 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192124
[email protected]1c773ea12009-04-28 19:58:422125 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192126 request.method = "GET";
2127 request.url = GURL("http://www.google.com/");
2128 request.load_flags = 0;
2129
[email protected]b75b7b2f2009-10-06 00:54:532130 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432131 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532132 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192133
2134 MockRead data_reads[] = {
2135 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432136 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192137 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422138 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192139 };
[email protected]31a2bfe2010-02-09 08:03:392140 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592141 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192142
2143 TestCompletionCallback callback;
2144
[email protected]5a1d7ca2010-04-28 20:12:272145 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422146 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192147
2148 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422149 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192150
[email protected]1c773ea12009-04-28 19:58:422151 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192152 EXPECT_TRUE(response == NULL);
2153}
[email protected]f4e426b2008-11-05 00:24:492154
2155// Make sure that we don't try to reuse a TCPClientSocket when failing to
2156// establish tunnel.
2157// http://code.google.com/p/chromium/issues/detail?id=3772
2158TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2159 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592160 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012161
[email protected]228ff742009-06-05 01:19:592162 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492163
[email protected]5695b8c2009-09-30 21:36:432164 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492165
[email protected]1c773ea12009-04-28 19:58:422166 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492167 request.method = "GET";
2168 request.url = GURL("https://www.google.com/");
2169 request.load_flags = 0;
2170
2171 // Since we have proxy, should try to establish tunnel.
2172 MockWrite data_writes1[] = {
2173 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452174 "Host: www.google.com\r\n"
2175 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492176 };
2177
[email protected]77848d12008-11-14 00:00:222178 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492179 // connection. Usually a proxy would return 501 (not implemented),
2180 // or 200 (tunnel established).
2181 MockRead data_reads1[] = {
2182 MockRead("HTTP/1.1 404 Not Found\r\n"),
2183 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422184 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492185 };
2186
[email protected]31a2bfe2010-02-09 08:03:392187 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2188 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592189 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492190
2191 TestCompletionCallback callback1;
2192
[email protected]5a1d7ca2010-04-28 20:12:272193 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422194 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492195
2196 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422197 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492198
[email protected]1c773ea12009-04-28 19:58:422199 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082200 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492201
[email protected]b4404c02009-04-10 16:38:522202 // Empty the current queue. This is necessary because idle sockets are
2203 // added to the connection pool asynchronously with a PostTask.
2204 MessageLoop::current()->RunAllPending();
2205
[email protected]f4e426b2008-11-05 00:24:492206 // We now check to make sure the TCPClientSocket was not added back to
2207 // the pool.
[email protected]a937a06d2009-08-19 21:19:242208 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492209 trans.reset();
[email protected]b4404c02009-04-10 16:38:522210 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492211 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242212 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492213}
[email protected]372d34a2008-11-05 21:30:512214
[email protected]1b157c02009-04-21 01:55:402215// Make sure that we recycle a socket after reading all of the response body.
2216TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592217 SessionDependencies session_deps;
2218 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402219
[email protected]5695b8c2009-09-30 21:36:432220 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402221
[email protected]1c773ea12009-04-28 19:58:422222 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402223 request.method = "GET";
2224 request.url = GURL("http://www.google.com/");
2225 request.load_flags = 0;
2226
2227 MockRead data_reads[] = {
2228 // A part of the response body is received with the response headers.
2229 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2230 // The rest of the response body is received in two parts.
2231 MockRead("lo"),
2232 MockRead(" world"),
2233 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422234 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402235 };
2236
[email protected]31a2bfe2010-02-09 08:03:392237 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592238 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402239
2240 TestCompletionCallback callback;
2241
[email protected]5a1d7ca2010-04-28 20:12:272242 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422243 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402244
2245 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422246 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402247
[email protected]1c773ea12009-04-28 19:58:422248 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402249 EXPECT_TRUE(response != NULL);
2250
2251 EXPECT_TRUE(response->headers != NULL);
2252 std::string status_line = response->headers->GetStatusLine();
2253 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2254
[email protected]a937a06d2009-08-19 21:19:242255 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402256
2257 std::string response_data;
2258 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422259 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402260 EXPECT_EQ("hello world", response_data);
2261
2262 // Empty the current queue. This is necessary because idle sockets are
2263 // added to the connection pool asynchronously with a PostTask.
2264 MessageLoop::current()->RunAllPending();
2265
2266 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242267 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402268}
2269
[email protected]b4404c02009-04-10 16:38:522270// Make sure that we recycle a socket after a zero-length response.
2271// http://crbug.com/9880
2272TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592273 SessionDependencies session_deps;
2274 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522275
[email protected]5695b8c2009-09-30 21:36:432276 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522277
[email protected]1c773ea12009-04-28 19:58:422278 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522279 request.method = "GET";
2280 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2281 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2282 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2283 "rt=prt.2642,ol.2649,xjs.2951");
2284 request.load_flags = 0;
2285
2286 MockRead data_reads[] = {
2287 MockRead("HTTP/1.1 204 No Content\r\n"
2288 "Content-Length: 0\r\n"
2289 "Content-Type: text/html\r\n\r\n"),
2290 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422291 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522292 };
2293
[email protected]31a2bfe2010-02-09 08:03:392294 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592295 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522296
2297 TestCompletionCallback callback;
2298
[email protected]5a1d7ca2010-04-28 20:12:272299 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422300 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522301
2302 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422303 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522304
[email protected]1c773ea12009-04-28 19:58:422305 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522306 EXPECT_TRUE(response != NULL);
2307
2308 EXPECT_TRUE(response->headers != NULL);
2309 std::string status_line = response->headers->GetStatusLine();
2310 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2311
[email protected]a937a06d2009-08-19 21:19:242312 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522313
2314 std::string response_data;
2315 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422316 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522317 EXPECT_EQ("", response_data);
2318
2319 // Empty the current queue. This is necessary because idle sockets are
2320 // added to the connection pool asynchronously with a PostTask.
2321 MessageLoop::current()->RunAllPending();
2322
2323 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242324 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522325}
2326
[email protected]372d34a2008-11-05 21:30:512327TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422328 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512329 // Transaction 1: a GET request that succeeds. The socket is recycled
2330 // after use.
2331 request[0].method = "GET";
2332 request[0].url = GURL("http://www.google.com/");
2333 request[0].load_flags = 0;
2334 // Transaction 2: a POST request. Reuses the socket kept alive from
2335 // transaction 1. The first attempts fails when writing the POST data.
2336 // This causes the transaction to retry with a new socket. The second
2337 // attempt succeeds.
2338 request[1].method = "POST";
2339 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422340 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512341 request[1].upload_data->AppendBytes("foo", 3);
2342 request[1].load_flags = 0;
2343
[email protected]228ff742009-06-05 01:19:592344 SessionDependencies session_deps;
2345 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512346
2347 // The first socket is used for transaction 1 and the first attempt of
2348 // transaction 2.
2349
2350 // The response of transaction 1.
2351 MockRead data_reads1[] = {
2352 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2353 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422354 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512355 };
2356 // The mock write results of transaction 1 and the first attempt of
2357 // transaction 2.
2358 MockWrite data_writes1[] = {
2359 MockWrite(false, 64), // GET
2360 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422361 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512362 };
[email protected]31a2bfe2010-02-09 08:03:392363 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2364 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512365
2366 // The second socket is used for the second attempt of transaction 2.
2367
2368 // The response of transaction 2.
2369 MockRead data_reads2[] = {
2370 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2371 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422372 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512373 };
2374 // The mock write results of the second attempt of transaction 2.
2375 MockWrite data_writes2[] = {
2376 MockWrite(false, 93), // POST
2377 MockWrite(false, 3), // POST data
2378 };
[email protected]31a2bfe2010-02-09 08:03:392379 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2380 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512381
[email protected]5ecc992a42009-11-11 01:41:592382 session_deps.socket_factory.AddSocketDataProvider(&data1);
2383 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512384
2385 const char* kExpectedResponseData[] = {
2386 "hello world", "welcome"
2387 };
2388
2389 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422390 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432391 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512392
2393 TestCompletionCallback callback;
2394
[email protected]5a1d7ca2010-04-28 20:12:272395 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422396 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512397
2398 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422399 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512400
[email protected]1c773ea12009-04-28 19:58:422401 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512402 EXPECT_TRUE(response != NULL);
2403
2404 EXPECT_TRUE(response->headers != NULL);
2405 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2406
2407 std::string response_data;
2408 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422409 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512410 EXPECT_EQ(kExpectedResponseData[i], response_data);
2411 }
2412}
[email protected]f9ee6b52008-11-08 06:46:232413
2414// Test the request-challenge-retry sequence for basic auth when there is
2415// an identity in the URL. The request should be sent as normal, but when
2416// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322417TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592418 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402419 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432420 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232421
[email protected]1c773ea12009-04-28 19:58:422422 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232423 request.method = "GET";
2424 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292425 request.url = GURL("http://foo:b@[email protected]/");
2426
2427 // The password contains an escaped character -- for this test to pass it
2428 // will need to be unescaped by HttpNetworkTransaction.
2429 EXPECT_EQ("b%40r", request.url.password());
2430
[email protected]ea9dc9a2009-09-05 00:43:322431 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232432
2433 MockWrite data_writes1[] = {
2434 MockWrite("GET / HTTP/1.1\r\n"
2435 "Host: www.google.com\r\n"
2436 "Connection: keep-alive\r\n\r\n"),
2437 };
2438
2439 MockRead data_reads1[] = {
2440 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2441 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2442 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422443 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232444 };
2445
2446 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322447 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232448 MockWrite data_writes2[] = {
2449 MockWrite("GET / HTTP/1.1\r\n"
2450 "Host: www.google.com\r\n"
2451 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292452 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232453 };
2454
2455 MockRead data_reads2[] = {
2456 MockRead("HTTP/1.0 200 OK\r\n"),
2457 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422458 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232459 };
2460
[email protected]31a2bfe2010-02-09 08:03:392461 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2462 data_writes1, arraysize(data_writes1));
2463 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2464 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592465 session_deps.socket_factory.AddSocketDataProvider(&data1);
2466 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232467
2468 TestCompletionCallback callback1;
2469
[email protected]5a1d7ca2010-04-28 20:12:272470 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422471 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232472
2473 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422474 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232475
[email protected]0757e7702009-03-27 04:00:222476 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2477 TestCompletionCallback callback2;
2478 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422479 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222480 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422481 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222482 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2483
[email protected]1c773ea12009-04-28 19:58:422484 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232485 EXPECT_FALSE(response == NULL);
2486
2487 // There is no challenge info, since the identity in URL worked.
2488 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2489
2490 EXPECT_EQ(100, response->headers->GetContentLength());
2491
2492 // Empty the current queue.
2493 MessageLoop::current()->RunAllPending();
2494}
2495
[email protected]ea9dc9a2009-09-05 00:43:322496// Test the request-challenge-retry sequence for basic auth when there is
2497// an incorrect identity in the URL. The identity from the URL should be used
2498// only once.
2499TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2500 SessionDependencies session_deps;
2501 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432502 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322503
2504 HttpRequestInfo request;
2505 request.method = "GET";
2506 // Note: the URL has a username:password in it. The password "baz" is
2507 // wrong (should be "bar").
2508 request.url = GURL("http://foo:[email protected]/");
2509
2510 request.load_flags = LOAD_NORMAL;
2511
2512 MockWrite data_writes1[] = {
2513 MockWrite("GET / HTTP/1.1\r\n"
2514 "Host: www.google.com\r\n"
2515 "Connection: keep-alive\r\n\r\n"),
2516 };
2517
2518 MockRead data_reads1[] = {
2519 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2520 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2521 MockRead("Content-Length: 10\r\n\r\n"),
2522 MockRead(false, ERR_FAILED),
2523 };
2524
2525 // After the challenge above, the transaction will be restarted using the
2526 // identity from the url (foo, baz) to answer the challenge.
2527 MockWrite data_writes2[] = {
2528 MockWrite("GET / HTTP/1.1\r\n"
2529 "Host: www.google.com\r\n"
2530 "Connection: keep-alive\r\n"
2531 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2532 };
2533
2534 MockRead data_reads2[] = {
2535 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2536 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2537 MockRead("Content-Length: 10\r\n\r\n"),
2538 MockRead(false, ERR_FAILED),
2539 };
2540
2541 // After the challenge above, the transaction will be restarted using the
2542 // identity supplied by the user (foo, bar) to answer the challenge.
2543 MockWrite data_writes3[] = {
2544 MockWrite("GET / HTTP/1.1\r\n"
2545 "Host: www.google.com\r\n"
2546 "Connection: keep-alive\r\n"
2547 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2548 };
2549
2550 MockRead data_reads3[] = {
2551 MockRead("HTTP/1.0 200 OK\r\n"),
2552 MockRead("Content-Length: 100\r\n\r\n"),
2553 MockRead(false, OK),
2554 };
2555
[email protected]31a2bfe2010-02-09 08:03:392556 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2557 data_writes1, arraysize(data_writes1));
2558 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2559 data_writes2, arraysize(data_writes2));
2560 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2561 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592562 session_deps.socket_factory.AddSocketDataProvider(&data1);
2563 session_deps.socket_factory.AddSocketDataProvider(&data2);
2564 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322565
2566 TestCompletionCallback callback1;
2567
[email protected]5a1d7ca2010-04-28 20:12:272568 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322569 EXPECT_EQ(ERR_IO_PENDING, rv);
2570
2571 rv = callback1.WaitForResult();
2572 EXPECT_EQ(OK, rv);
2573
2574 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2575 TestCompletionCallback callback2;
2576 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2577 EXPECT_EQ(ERR_IO_PENDING, rv);
2578 rv = callback2.WaitForResult();
2579 EXPECT_EQ(OK, rv);
2580 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2581
2582 const HttpResponseInfo* response = trans->GetResponseInfo();
2583 EXPECT_FALSE(response == NULL);
2584 // The password prompt info should have been set in response->auth_challenge.
2585 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2586
2587 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2588 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2589 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2590
2591 TestCompletionCallback callback3;
2592 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2593 EXPECT_EQ(ERR_IO_PENDING, rv);
2594 rv = callback3.WaitForResult();
2595 EXPECT_EQ(OK, rv);
2596 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2597
2598 response = trans->GetResponseInfo();
2599 EXPECT_FALSE(response == NULL);
2600
2601 // There is no challenge info, since the identity worked.
2602 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2603
2604 EXPECT_EQ(100, response->headers->GetContentLength());
2605
2606 // Empty the current queue.
2607 MessageLoop::current()->RunAllPending();
2608}
2609
[email protected]f9ee6b52008-11-08 06:46:232610// Test that previously tried username/passwords for a realm get re-used.
2611TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592612 SessionDependencies session_deps;
2613 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232614
2615 // Transaction 1: authenticate (foo, bar) on MyRealm1
2616 {
[email protected]5695b8c2009-09-30 21:36:432617 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232618
[email protected]1c773ea12009-04-28 19:58:422619 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232620 request.method = "GET";
2621 request.url = GURL("http://www.google.com/x/y/z");
2622 request.load_flags = 0;
2623
2624 MockWrite data_writes1[] = {
2625 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2626 "Host: www.google.com\r\n"
2627 "Connection: keep-alive\r\n\r\n"),
2628 };
2629
2630 MockRead data_reads1[] = {
2631 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2632 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2633 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422634 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232635 };
2636
2637 // Resend with authorization (username=foo, password=bar)
2638 MockWrite data_writes2[] = {
2639 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2640 "Host: www.google.com\r\n"
2641 "Connection: keep-alive\r\n"
2642 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2643 };
2644
2645 // Sever accepts the authorization.
2646 MockRead data_reads2[] = {
2647 MockRead("HTTP/1.0 200 OK\r\n"),
2648 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422649 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232650 };
2651
[email protected]31a2bfe2010-02-09 08:03:392652 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2653 data_writes1, arraysize(data_writes1));
2654 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2655 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592656 session_deps.socket_factory.AddSocketDataProvider(&data1);
2657 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232658
2659 TestCompletionCallback callback1;
2660
[email protected]5a1d7ca2010-04-28 20:12:272661 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422662 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232663
2664 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422665 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232666
[email protected]1c773ea12009-04-28 19:58:422667 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232668 EXPECT_FALSE(response == NULL);
2669
2670 // The password prompt info should have been set in
2671 // response->auth_challenge.
2672 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2673
[email protected]71e4573a2009-05-21 22:03:002674 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232675 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2676 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2677
2678 TestCompletionCallback callback2;
2679
2680 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422681 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232682
2683 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422684 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232685
2686 response = trans->GetResponseInfo();
2687 EXPECT_FALSE(response == NULL);
2688 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2689 EXPECT_EQ(100, response->headers->GetContentLength());
2690 }
2691
2692 // ------------------------------------------------------------------------
2693
2694 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2695 {
[email protected]5695b8c2009-09-30 21:36:432696 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232697
[email protected]1c773ea12009-04-28 19:58:422698 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232699 request.method = "GET";
2700 // Note that Transaction 1 was at /x/y/z, so this is in the same
2701 // protection space as MyRealm1.
2702 request.url = GURL("http://www.google.com/x/y/a/b");
2703 request.load_flags = 0;
2704
2705 MockWrite data_writes1[] = {
2706 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2707 "Host: www.google.com\r\n"
2708 "Connection: keep-alive\r\n"
2709 // Send preemptive authorization for MyRealm1
2710 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2711 };
2712
2713 // The server didn't like the preemptive authorization, and
2714 // challenges us for a different realm (MyRealm2).
2715 MockRead data_reads1[] = {
2716 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2717 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2718 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422719 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232720 };
2721
2722 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2723 MockWrite data_writes2[] = {
2724 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2725 "Host: www.google.com\r\n"
2726 "Connection: keep-alive\r\n"
2727 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2728 };
2729
2730 // Sever accepts the authorization.
2731 MockRead data_reads2[] = {
2732 MockRead("HTTP/1.0 200 OK\r\n"),
2733 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422734 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232735 };
2736
[email protected]31a2bfe2010-02-09 08:03:392737 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2738 data_writes1, arraysize(data_writes1));
2739 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2740 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592741 session_deps.socket_factory.AddSocketDataProvider(&data1);
2742 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232743
2744 TestCompletionCallback callback1;
2745
[email protected]5a1d7ca2010-04-28 20:12:272746 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422747 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232748
2749 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422750 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232751
[email protected]1c773ea12009-04-28 19:58:422752 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232753 EXPECT_FALSE(response == NULL);
2754
2755 // The password prompt info should have been set in
2756 // response->auth_challenge.
2757 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2758
[email protected]71e4573a2009-05-21 22:03:002759 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232760 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2761 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2762
2763 TestCompletionCallback callback2;
2764
2765 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422766 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232767
2768 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422769 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232770
2771 response = trans->GetResponseInfo();
2772 EXPECT_FALSE(response == NULL);
2773 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2774 EXPECT_EQ(100, response->headers->GetContentLength());
2775 }
2776
2777 // ------------------------------------------------------------------------
2778
2779 // Transaction 3: Resend a request in MyRealm's protection space --
2780 // succeed with preemptive authorization.
2781 {
[email protected]5695b8c2009-09-30 21:36:432782 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232783
[email protected]1c773ea12009-04-28 19:58:422784 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232785 request.method = "GET";
2786 request.url = GURL("http://www.google.com/x/y/z2");
2787 request.load_flags = 0;
2788
2789 MockWrite data_writes1[] = {
2790 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2791 "Host: www.google.com\r\n"
2792 "Connection: keep-alive\r\n"
2793 // The authorization for MyRealm1 gets sent preemptively
2794 // (since the url is in the same protection space)
2795 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2796 };
2797
2798 // Sever accepts the preemptive authorization
2799 MockRead data_reads1[] = {
2800 MockRead("HTTP/1.0 200 OK\r\n"),
2801 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422802 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232803 };
2804
[email protected]31a2bfe2010-02-09 08:03:392805 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2806 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592807 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232808
2809 TestCompletionCallback callback1;
2810
[email protected]5a1d7ca2010-04-28 20:12:272811 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422812 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232813
2814 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422815 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232816
[email protected]1c773ea12009-04-28 19:58:422817 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232818 EXPECT_FALSE(response == NULL);
2819
2820 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2821 EXPECT_EQ(100, response->headers->GetContentLength());
2822 }
2823
2824 // ------------------------------------------------------------------------
2825
2826 // Transaction 4: request another URL in MyRealm (however the
2827 // url is not known to belong to the protection space, so no pre-auth).
2828 {
[email protected]5695b8c2009-09-30 21:36:432829 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232830
[email protected]1c773ea12009-04-28 19:58:422831 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232832 request.method = "GET";
2833 request.url = GURL("http://www.google.com/x/1");
2834 request.load_flags = 0;
2835
2836 MockWrite data_writes1[] = {
2837 MockWrite("GET /x/1 HTTP/1.1\r\n"
2838 "Host: www.google.com\r\n"
2839 "Connection: keep-alive\r\n\r\n"),
2840 };
2841
2842 MockRead data_reads1[] = {
2843 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2844 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2845 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422846 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232847 };
2848
2849 // Resend with authorization from MyRealm's cache.
2850 MockWrite data_writes2[] = {
2851 MockWrite("GET /x/1 HTTP/1.1\r\n"
2852 "Host: www.google.com\r\n"
2853 "Connection: keep-alive\r\n"
2854 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2855 };
2856
2857 // Sever accepts the authorization.
2858 MockRead data_reads2[] = {
2859 MockRead("HTTP/1.0 200 OK\r\n"),
2860 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422861 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232862 };
2863
[email protected]31a2bfe2010-02-09 08:03:392864 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2865 data_writes1, arraysize(data_writes1));
2866 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2867 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592868 session_deps.socket_factory.AddSocketDataProvider(&data1);
2869 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232870
2871 TestCompletionCallback callback1;
2872
[email protected]5a1d7ca2010-04-28 20:12:272873 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422874 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232875
2876 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422877 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232878
[email protected]0757e7702009-03-27 04:00:222879 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2880 TestCompletionCallback callback2;
2881 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422882 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222883 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422884 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222885 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2886
[email protected]1c773ea12009-04-28 19:58:422887 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232888 EXPECT_FALSE(response == NULL);
2889 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2890 EXPECT_EQ(100, response->headers->GetContentLength());
2891 }
2892
2893 // ------------------------------------------------------------------------
2894
2895 // Transaction 5: request a URL in MyRealm, but the server rejects the
2896 // cached identity. Should invalidate and re-prompt.
2897 {
[email protected]5695b8c2009-09-30 21:36:432898 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232899
[email protected]1c773ea12009-04-28 19:58:422900 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232901 request.method = "GET";
2902 request.url = GURL("http://www.google.com/p/q/t");
2903 request.load_flags = 0;
2904
2905 MockWrite data_writes1[] = {
2906 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2907 "Host: www.google.com\r\n"
2908 "Connection: keep-alive\r\n\r\n"),
2909 };
2910
2911 MockRead data_reads1[] = {
2912 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2913 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2914 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422915 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232916 };
2917
2918 // Resend with authorization from cache for MyRealm.
2919 MockWrite data_writes2[] = {
2920 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2921 "Host: www.google.com\r\n"
2922 "Connection: keep-alive\r\n"
2923 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2924 };
2925
2926 // Sever rejects the authorization.
2927 MockRead data_reads2[] = {
2928 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2929 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2930 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422931 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232932 };
2933
2934 // At this point we should prompt for new credentials for MyRealm.
2935 // Restart with username=foo3, password=foo4.
2936 MockWrite data_writes3[] = {
2937 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2938 "Host: www.google.com\r\n"
2939 "Connection: keep-alive\r\n"
2940 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2941 };
2942
2943 // Sever accepts the authorization.
2944 MockRead data_reads3[] = {
2945 MockRead("HTTP/1.0 200 OK\r\n"),
2946 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422947 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232948 };
2949
[email protected]31a2bfe2010-02-09 08:03:392950 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2951 data_writes1, arraysize(data_writes1));
2952 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2953 data_writes2, arraysize(data_writes2));
2954 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2955 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592956 session_deps.socket_factory.AddSocketDataProvider(&data1);
2957 session_deps.socket_factory.AddSocketDataProvider(&data2);
2958 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232959
2960 TestCompletionCallback callback1;
2961
[email protected]5a1d7ca2010-04-28 20:12:272962 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422963 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232964
2965 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422966 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232967
[email protected]0757e7702009-03-27 04:00:222968 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2969 TestCompletionCallback callback2;
2970 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422971 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222972 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422973 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222974 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2975
[email protected]1c773ea12009-04-28 19:58:422976 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232977 EXPECT_FALSE(response == NULL);
2978
2979 // The password prompt info should have been set in
2980 // response->auth_challenge.
2981 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2982
[email protected]71e4573a2009-05-21 22:03:002983 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232984 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2985 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2986
[email protected]0757e7702009-03-27 04:00:222987 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232988
[email protected]0757e7702009-03-27 04:00:222989 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422990 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232991
[email protected]0757e7702009-03-27 04:00:222992 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422993 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232994
2995 response = trans->GetResponseInfo();
2996 EXPECT_FALSE(response == NULL);
2997 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2998 EXPECT_EQ(100, response->headers->GetContentLength());
2999 }
3000}
[email protected]89ceba9a2009-03-21 03:46:063001
[email protected]3c32c5f2010-05-18 15:18:123002// Tests that nonce count increments when multiple auth attempts
3003// are started with the same nonce.
3004TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3005 SessionDependencies session_deps;
3006 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3007 HttpAuthHandlerDigest::SetFixedCnonce(true);
3008
3009 // Transaction 1: authenticate (foo, bar) on MyRealm1
3010 {
3011 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3012
3013 HttpRequestInfo request;
3014 request.method = "GET";
3015 request.url = GURL("http://www.google.com/x/y/z");
3016 request.load_flags = 0;
3017
3018 MockWrite data_writes1[] = {
3019 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3020 "Host: www.google.com\r\n"
3021 "Connection: keep-alive\r\n\r\n"),
3022 };
3023
3024 MockRead data_reads1[] = {
3025 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3026 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3027 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3028 MockRead(false, OK),
3029 };
3030
3031 // Resend with authorization (username=foo, password=bar)
3032 MockWrite data_writes2[] = {
3033 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3034 "Host: www.google.com\r\n"
3035 "Connection: keep-alive\r\n"
3036 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3037 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3038 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3039 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3040 };
3041
3042 // Sever accepts the authorization.
3043 MockRead data_reads2[] = {
3044 MockRead("HTTP/1.0 200 OK\r\n"),
3045 MockRead(false, OK),
3046 };
3047
3048 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3049 data_writes1, arraysize(data_writes1));
3050 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3051 data_writes2, arraysize(data_writes2));
3052 session_deps.socket_factory.AddSocketDataProvider(&data1);
3053 session_deps.socket_factory.AddSocketDataProvider(&data2);
3054
3055 TestCompletionCallback callback1;
3056
3057 int rv = trans->Start(&request, &callback1, BoundNetLog());
3058 EXPECT_EQ(ERR_IO_PENDING, rv);
3059
3060 rv = callback1.WaitForResult();
3061 EXPECT_EQ(OK, rv);
3062
3063 const HttpResponseInfo* response = trans->GetResponseInfo();
3064 ASSERT_FALSE(response == NULL);
3065
3066 // The password prompt info should have been set in
3067 // response->auth_challenge.
3068 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3069
3070 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3071 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3072 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3073
3074 TestCompletionCallback callback2;
3075
3076 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3077 EXPECT_EQ(ERR_IO_PENDING, rv);
3078
3079 rv = callback2.WaitForResult();
3080 EXPECT_EQ(OK, rv);
3081
3082 response = trans->GetResponseInfo();
3083 ASSERT_FALSE(response == NULL);
3084 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3085 }
3086
3087 // ------------------------------------------------------------------------
3088
3089 // Transaction 2: Request another resource in digestive's protection space.
3090 // This will preemptively add an Authorization header which should have an
3091 // "nc" value of 2 (as compared to 1 in the first use.
3092 {
3093 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3094
3095 HttpRequestInfo request;
3096 request.method = "GET";
3097 // Note that Transaction 1 was at /x/y/z, so this is in the same
3098 // protection space as digest.
3099 request.url = GURL("http://www.google.com/x/y/a/b");
3100 request.load_flags = 0;
3101
3102 MockWrite data_writes1[] = {
3103 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3104 "Host: www.google.com\r\n"
3105 "Connection: keep-alive\r\n"
3106 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3107 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3108 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3109 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3110 };
3111
3112 // Sever accepts the authorization.
3113 MockRead data_reads1[] = {
3114 MockRead("HTTP/1.0 200 OK\r\n"),
3115 MockRead("Content-Length: 100\r\n\r\n"),
3116 MockRead(false, OK),
3117 };
3118
3119 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3120 data_writes1, arraysize(data_writes1));
3121 session_deps.socket_factory.AddSocketDataProvider(&data1);
3122
3123 TestCompletionCallback callback1;
3124
3125 int rv = trans->Start(&request, &callback1, BoundNetLog());
3126 EXPECT_EQ(ERR_IO_PENDING, rv);
3127
3128 rv = callback1.WaitForResult();
3129 EXPECT_EQ(OK, rv);
3130
3131 const HttpResponseInfo* response = trans->GetResponseInfo();
3132 ASSERT_FALSE(response == NULL);
3133 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3134 }
3135}
3136
[email protected]89ceba9a2009-03-21 03:46:063137// Test the ResetStateForRestart() private method.
3138TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3139 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593140 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403141 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433142 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063143
3144 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063145 trans->read_buf_ = new IOBuffer(15);
3146 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573147 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063148
3149 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143150 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573151 response->auth_challenge = new AuthChallengeInfo();
3152 response->ssl_info.cert_status = -15;
3153 response->response_time = base::Time::Now();
3154 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063155
3156 { // Setup state for response_.vary_data
3157 HttpRequestInfo request;
3158 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3159 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573160 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433161 request.extra_headers.SetHeader("Foo", "1");
3162 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573163 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063164 }
3165
3166 // Cause the above state to be reset.
3167 trans->ResetStateForRestart();
3168
3169 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073170 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063171 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573172 EXPECT_EQ(0U, trans->request_headers_.size());
3173 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3174 EXPECT_TRUE(response->headers.get() == NULL);
3175 EXPECT_EQ(false, response->was_cached);
3176 EXPECT_EQ(0, response->ssl_info.cert_status);
3177 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063178}
3179
[email protected]bacff652009-03-31 17:50:333180// Test HTTPS connections to a site with a bad certificate
3181TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593182 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403183 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433184 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333185
3186 HttpRequestInfo request;
3187 request.method = "GET";
3188 request.url = GURL("https://www.google.com/");
3189 request.load_flags = 0;
3190
3191 MockWrite data_writes[] = {
3192 MockWrite("GET / HTTP/1.1\r\n"
3193 "Host: www.google.com\r\n"
3194 "Connection: keep-alive\r\n\r\n"),
3195 };
3196
3197 MockRead data_reads[] = {
3198 MockRead("HTTP/1.0 200 OK\r\n"),
3199 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3200 MockRead("Content-Length: 100\r\n\r\n"),
3201 MockRead(false, OK),
3202 };
3203
[email protected]5ecc992a42009-11-11 01:41:593204 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393205 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3206 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593207 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3208 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333209
[email protected]5ecc992a42009-11-11 01:41:593210 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3211 session_deps.socket_factory.AddSocketDataProvider(&data);
3212 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3213 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333214
3215 TestCompletionCallback callback;
3216
[email protected]5a1d7ca2010-04-28 20:12:273217 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333218 EXPECT_EQ(ERR_IO_PENDING, rv);
3219
3220 rv = callback.WaitForResult();
3221 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3222
3223 rv = trans->RestartIgnoringLastError(&callback);
3224 EXPECT_EQ(ERR_IO_PENDING, rv);
3225
3226 rv = callback.WaitForResult();
3227 EXPECT_EQ(OK, rv);
3228
3229 const HttpResponseInfo* response = trans->GetResponseInfo();
3230
3231 EXPECT_FALSE(response == NULL);
3232 EXPECT_EQ(100, response->headers->GetContentLength());
3233}
3234
3235// Test HTTPS connections to a site with a bad certificate, going through a
3236// proxy
3237TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593238 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333239
3240 HttpRequestInfo request;
3241 request.method = "GET";
3242 request.url = GURL("https://www.google.com/");
3243 request.load_flags = 0;
3244
3245 MockWrite proxy_writes[] = {
3246 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453247 "Host: www.google.com\r\n"
3248 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333249 };
3250
3251 MockRead proxy_reads[] = {
3252 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423253 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333254 };
3255
3256 MockWrite data_writes[] = {
3257 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453258 "Host: www.google.com\r\n"
3259 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333260 MockWrite("GET / HTTP/1.1\r\n"
3261 "Host: www.google.com\r\n"
3262 "Connection: keep-alive\r\n\r\n"),
3263 };
3264
3265 MockRead data_reads[] = {
3266 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3267 MockRead("HTTP/1.0 200 OK\r\n"),
3268 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3269 MockRead("Content-Length: 100\r\n\r\n"),
3270 MockRead(false, OK),
3271 };
3272
[email protected]31a2bfe2010-02-09 08:03:393273 StaticSocketDataProvider ssl_bad_certificate(
3274 proxy_reads, arraysize(proxy_reads),
3275 proxy_writes, arraysize(proxy_writes));
3276 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3277 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593278 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3279 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333280
[email protected]5ecc992a42009-11-11 01:41:593281 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3282 session_deps.socket_factory.AddSocketDataProvider(&data);
3283 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3284 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333285
3286 TestCompletionCallback callback;
3287
3288 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593289 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333290
[email protected]d207a5f2009-06-04 05:28:403291 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433292 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333293
[email protected]5a1d7ca2010-04-28 20:12:273294 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333295 EXPECT_EQ(ERR_IO_PENDING, rv);
3296
3297 rv = callback.WaitForResult();
3298 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3299
3300 rv = trans->RestartIgnoringLastError(&callback);
3301 EXPECT_EQ(ERR_IO_PENDING, rv);
3302
3303 rv = callback.WaitForResult();
3304 EXPECT_EQ(OK, rv);
3305
3306 const HttpResponseInfo* response = trans->GetResponseInfo();
3307
3308 EXPECT_FALSE(response == NULL);
3309 EXPECT_EQ(100, response->headers->GetContentLength());
3310 }
3311}
3312
[email protected]1c773ea12009-04-28 19:58:423313TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593314 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403315 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433316 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423317
3318 HttpRequestInfo request;
3319 request.method = "GET";
3320 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433321 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3322 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423323
3324 MockWrite data_writes[] = {
3325 MockWrite("GET / HTTP/1.1\r\n"
3326 "Host: www.google.com\r\n"
3327 "Connection: keep-alive\r\n"
3328 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3329 };
3330
3331 // Lastly, the server responds with the actual content.
3332 MockRead data_reads[] = {
3333 MockRead("HTTP/1.0 200 OK\r\n"),
3334 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3335 MockRead("Content-Length: 100\r\n\r\n"),
3336 MockRead(false, OK),
3337 };
3338
[email protected]31a2bfe2010-02-09 08:03:393339 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3340 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593341 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423342
3343 TestCompletionCallback callback;
3344
[email protected]5a1d7ca2010-04-28 20:12:273345 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423346 EXPECT_EQ(ERR_IO_PENDING, rv);
3347
3348 rv = callback.WaitForResult();
3349 EXPECT_EQ(OK, rv);
3350}
3351
3352TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593353 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403354 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433355 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423356
3357 HttpRequestInfo request;
3358 request.method = "GET";
3359 request.url = GURL("http://www.google.com/");
3360 request.load_flags = 0;
3361 request.referrer = GURL("http://the.previous.site.com/");
3362
3363 MockWrite data_writes[] = {
3364 MockWrite("GET / HTTP/1.1\r\n"
3365 "Host: www.google.com\r\n"
3366 "Connection: keep-alive\r\n"
3367 "Referer: http://the.previous.site.com/\r\n\r\n"),
3368 };
3369
3370 // Lastly, the server responds with the actual content.
3371 MockRead data_reads[] = {
3372 MockRead("HTTP/1.0 200 OK\r\n"),
3373 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3374 MockRead("Content-Length: 100\r\n\r\n"),
3375 MockRead(false, OK),
3376 };
3377
[email protected]31a2bfe2010-02-09 08:03:393378 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3379 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593380 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423381
3382 TestCompletionCallback callback;
3383
[email protected]5a1d7ca2010-04-28 20:12:273384 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423385 EXPECT_EQ(ERR_IO_PENDING, rv);
3386
3387 rv = callback.WaitForResult();
3388 EXPECT_EQ(OK, rv);
3389}
3390
3391TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593392 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403393 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433394 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423395
3396 HttpRequestInfo request;
3397 request.method = "POST";
3398 request.url = GURL("http://www.google.com/");
3399
3400 MockWrite data_writes[] = {
3401 MockWrite("POST / HTTP/1.1\r\n"
3402 "Host: www.google.com\r\n"
3403 "Connection: keep-alive\r\n"
3404 "Content-Length: 0\r\n\r\n"),
3405 };
3406
3407 // Lastly, the server responds with the actual content.
3408 MockRead data_reads[] = {
3409 MockRead("HTTP/1.0 200 OK\r\n"),
3410 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3411 MockRead("Content-Length: 100\r\n\r\n"),
3412 MockRead(false, OK),
3413 };
3414
[email protected]31a2bfe2010-02-09 08:03:393415 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3416 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593417 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423418
3419 TestCompletionCallback callback;
3420
[email protected]5a1d7ca2010-04-28 20:12:273421 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423422 EXPECT_EQ(ERR_IO_PENDING, rv);
3423
3424 rv = callback.WaitForResult();
3425 EXPECT_EQ(OK, rv);
3426}
3427
3428TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593429 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403430 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433431 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423432
3433 HttpRequestInfo request;
3434 request.method = "PUT";
3435 request.url = GURL("http://www.google.com/");
3436
3437 MockWrite data_writes[] = {
3438 MockWrite("PUT / HTTP/1.1\r\n"
3439 "Host: www.google.com\r\n"
3440 "Connection: keep-alive\r\n"
3441 "Content-Length: 0\r\n\r\n"),
3442 };
3443
3444 // Lastly, the server responds with the actual content.
3445 MockRead data_reads[] = {
3446 MockRead("HTTP/1.0 200 OK\r\n"),
3447 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3448 MockRead("Content-Length: 100\r\n\r\n"),
3449 MockRead(false, OK),
3450 };
3451
[email protected]31a2bfe2010-02-09 08:03:393452 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3453 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593454 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423455
3456 TestCompletionCallback callback;
3457
[email protected]5a1d7ca2010-04-28 20:12:273458 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423459 EXPECT_EQ(ERR_IO_PENDING, rv);
3460
3461 rv = callback.WaitForResult();
3462 EXPECT_EQ(OK, rv);
3463}
3464
3465TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593466 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403467 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433468 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423469
3470 HttpRequestInfo request;
3471 request.method = "HEAD";
3472 request.url = GURL("http://www.google.com/");
3473
3474 MockWrite data_writes[] = {
3475 MockWrite("HEAD / HTTP/1.1\r\n"
3476 "Host: www.google.com\r\n"
3477 "Connection: keep-alive\r\n"
3478 "Content-Length: 0\r\n\r\n"),
3479 };
3480
3481 // Lastly, the server responds with the actual content.
3482 MockRead data_reads[] = {
3483 MockRead("HTTP/1.0 200 OK\r\n"),
3484 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3485 MockRead("Content-Length: 100\r\n\r\n"),
3486 MockRead(false, OK),
3487 };
3488
[email protected]31a2bfe2010-02-09 08:03:393489 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3490 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593491 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423492
3493 TestCompletionCallback callback;
3494
[email protected]5a1d7ca2010-04-28 20:12:273495 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423496 EXPECT_EQ(ERR_IO_PENDING, rv);
3497
3498 rv = callback.WaitForResult();
3499 EXPECT_EQ(OK, rv);
3500}
3501
3502TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593503 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403504 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433505 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423506
3507 HttpRequestInfo request;
3508 request.method = "GET";
3509 request.url = GURL("http://www.google.com/");
3510 request.load_flags = LOAD_BYPASS_CACHE;
3511
3512 MockWrite data_writes[] = {
3513 MockWrite("GET / HTTP/1.1\r\n"
3514 "Host: www.google.com\r\n"
3515 "Connection: keep-alive\r\n"
3516 "Pragma: no-cache\r\n"
3517 "Cache-Control: no-cache\r\n\r\n"),
3518 };
3519
3520 // Lastly, the server responds with the actual content.
3521 MockRead data_reads[] = {
3522 MockRead("HTTP/1.0 200 OK\r\n"),
3523 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3524 MockRead("Content-Length: 100\r\n\r\n"),
3525 MockRead(false, OK),
3526 };
3527
[email protected]31a2bfe2010-02-09 08:03:393528 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3529 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593530 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423531
3532 TestCompletionCallback callback;
3533
[email protected]5a1d7ca2010-04-28 20:12:273534 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423535 EXPECT_EQ(ERR_IO_PENDING, rv);
3536
3537 rv = callback.WaitForResult();
3538 EXPECT_EQ(OK, rv);
3539}
3540
3541TEST_F(HttpNetworkTransactionTest,
3542 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593543 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403544 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433545 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423546
3547 HttpRequestInfo request;
3548 request.method = "GET";
3549 request.url = GURL("http://www.google.com/");
3550 request.load_flags = LOAD_VALIDATE_CACHE;
3551
3552 MockWrite data_writes[] = {
3553 MockWrite("GET / HTTP/1.1\r\n"
3554 "Host: www.google.com\r\n"
3555 "Connection: keep-alive\r\n"
3556 "Cache-Control: max-age=0\r\n\r\n"),
3557 };
3558
3559 // Lastly, the server responds with the actual content.
3560 MockRead data_reads[] = {
3561 MockRead("HTTP/1.0 200 OK\r\n"),
3562 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3563 MockRead("Content-Length: 100\r\n\r\n"),
3564 MockRead(false, OK),
3565 };
3566
[email protected]31a2bfe2010-02-09 08:03:393567 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3568 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593569 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423570
3571 TestCompletionCallback callback;
3572
[email protected]5a1d7ca2010-04-28 20:12:273573 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423574 EXPECT_EQ(ERR_IO_PENDING, rv);
3575
3576 rv = callback.WaitForResult();
3577 EXPECT_EQ(OK, rv);
3578}
3579
3580TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593581 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403582 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433583 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423584
3585 HttpRequestInfo request;
3586 request.method = "GET";
3587 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433588 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423589
3590 MockWrite data_writes[] = {
3591 MockWrite("GET / HTTP/1.1\r\n"
3592 "Host: www.google.com\r\n"
3593 "Connection: keep-alive\r\n"
3594 "FooHeader: Bar\r\n\r\n"),
3595 };
3596
3597 // Lastly, the server responds with the actual content.
3598 MockRead data_reads[] = {
3599 MockRead("HTTP/1.0 200 OK\r\n"),
3600 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3601 MockRead("Content-Length: 100\r\n\r\n"),
3602 MockRead(false, OK),
3603 };
3604
[email protected]31a2bfe2010-02-09 08:03:393605 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3606 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593607 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423608
3609 TestCompletionCallback callback;
3610
[email protected]5a1d7ca2010-04-28 20:12:273611 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423612 EXPECT_EQ(ERR_IO_PENDING, rv);
3613
3614 rv = callback.WaitForResult();
3615 EXPECT_EQ(OK, rv);
3616}
3617
[email protected]270c6412010-03-29 22:02:473618TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3619 SessionDependencies session_deps;
3620 scoped_ptr<HttpTransaction> trans(
3621 new HttpNetworkTransaction(CreateSession(&session_deps)));
3622
3623 HttpRequestInfo request;
3624 request.method = "GET";
3625 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433626 request.extra_headers.SetHeader("referer", "www.foo.com");
3627 request.extra_headers.SetHeader("hEllo", "Kitty");
3628 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473629
3630 MockWrite data_writes[] = {
3631 MockWrite("GET / HTTP/1.1\r\n"
3632 "Host: www.google.com\r\n"
3633 "Connection: keep-alive\r\n"
3634 "hEllo: Kitty\r\n"
3635 "FoO: bar\r\n\r\n"),
3636 };
3637
3638 // Lastly, the server responds with the actual content.
3639 MockRead data_reads[] = {
3640 MockRead("HTTP/1.0 200 OK\r\n"),
3641 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3642 MockRead("Content-Length: 100\r\n\r\n"),
3643 MockRead(false, OK),
3644 };
3645
3646 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3647 data_writes, arraysize(data_writes));
3648 session_deps.socket_factory.AddSocketDataProvider(&data);
3649
3650 TestCompletionCallback callback;
3651
[email protected]5a1d7ca2010-04-28 20:12:273652 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473653 EXPECT_EQ(ERR_IO_PENDING, rv);
3654
3655 rv = callback.WaitForResult();
3656 EXPECT_EQ(OK, rv);
3657}
3658
[email protected]3cd17242009-06-23 02:59:023659TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093660 SessionDependencies session_deps(
3661 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023662
3663 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433664 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023665
3666 HttpRequestInfo request;
3667 request.method = "GET";
3668 request.url = GURL("http://www.google.com/");
3669 request.load_flags = 0;
3670
3671 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3672 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3673
3674 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353675 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023676 MockWrite("GET / HTTP/1.1\r\n"
3677 "Host: www.google.com\r\n"
3678 "Connection: keep-alive\r\n\r\n")
3679 };
3680
3681 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593682 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023683 MockRead("HTTP/1.0 200 OK\r\n"),
3684 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3685 MockRead("Payload"),
3686 MockRead(false, OK)
3687 };
3688
[email protected]31a2bfe2010-02-09 08:03:393689 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3690 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593691 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023692
3693 TestCompletionCallback callback;
3694
[email protected]5a1d7ca2010-04-28 20:12:273695 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023696 EXPECT_EQ(ERR_IO_PENDING, rv);
3697
3698 rv = callback.WaitForResult();
3699 EXPECT_EQ(OK, rv);
3700
3701 const HttpResponseInfo* response = trans->GetResponseInfo();
3702 EXPECT_FALSE(response == NULL);
3703
3704 std::string response_text;
3705 rv = ReadTransaction(trans.get(), &response_text);
3706 EXPECT_EQ(OK, rv);
3707 EXPECT_EQ("Payload", response_text);
3708}
3709
3710TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093711 SessionDependencies session_deps(
3712 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023713
3714 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433715 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023716
3717 HttpRequestInfo request;
3718 request.method = "GET";
3719 request.url = GURL("https://www.google.com/");
3720 request.load_flags = 0;
3721
3722 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3723 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3724
3725 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353726 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3727 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023728 MockWrite("GET / HTTP/1.1\r\n"
3729 "Host: www.google.com\r\n"
3730 "Connection: keep-alive\r\n\r\n")
3731 };
3732
3733 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353734 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3735 arraysize(read_buffer)),
3736 MockRead("HTTP/1.0 200 OK\r\n"),
3737 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3738 MockRead("Payload"),
3739 MockRead(false, OK)
3740 };
3741
[email protected]31a2bfe2010-02-09 08:03:393742 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3743 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593744 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353745
[email protected]5ecc992a42009-11-11 01:41:593746 SSLSocketDataProvider ssl(true, OK);
3747 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353748
3749 TestCompletionCallback callback;
3750
[email protected]5a1d7ca2010-04-28 20:12:273751 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353752 EXPECT_EQ(ERR_IO_PENDING, rv);
3753
3754 rv = callback.WaitForResult();
3755 EXPECT_EQ(OK, rv);
3756
3757 const HttpResponseInfo* response = trans->GetResponseInfo();
3758 EXPECT_FALSE(response == NULL);
3759
3760 std::string response_text;
3761 rv = ReadTransaction(trans.get(), &response_text);
3762 EXPECT_EQ(OK, rv);
3763 EXPECT_EQ("Payload", response_text);
3764}
3765
3766TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093767 SessionDependencies session_deps(
3768 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353769
3770 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433771 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353772
3773 HttpRequestInfo request;
3774 request.method = "GET";
3775 request.url = GURL("http://www.google.com/");
3776 request.load_flags = 0;
3777
3778 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3779 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373780 const char kSOCKS5OkRequest[] = {
3781 0x05, // Version
3782 0x01, // Command (CONNECT)
3783 0x00, // Reserved.
3784 0x03, // Address type (DOMAINNAME).
3785 0x0E, // Length of domain (14)
3786 // Domain string:
3787 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3788 0x00, 0x50, // 16-bit port (80)
3789 };
[email protected]e0c27be2009-07-15 13:09:353790 const char kSOCKS5OkResponse[] =
3791 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3792
3793 MockWrite data_writes[] = {
3794 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3795 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3796 MockWrite("GET / HTTP/1.1\r\n"
3797 "Host: www.google.com\r\n"
3798 "Connection: keep-alive\r\n\r\n")
3799 };
3800
3801 MockRead data_reads[] = {
3802 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3803 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3804 MockRead("HTTP/1.0 200 OK\r\n"),
3805 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3806 MockRead("Payload"),
3807 MockRead(false, OK)
3808 };
3809
[email protected]31a2bfe2010-02-09 08:03:393810 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3811 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593812 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353813
3814 TestCompletionCallback callback;
3815
[email protected]5a1d7ca2010-04-28 20:12:273816 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353817 EXPECT_EQ(ERR_IO_PENDING, rv);
3818
3819 rv = callback.WaitForResult();
3820 EXPECT_EQ(OK, rv);
3821
3822 const HttpResponseInfo* response = trans->GetResponseInfo();
3823 EXPECT_FALSE(response == NULL);
3824
3825 std::string response_text;
3826 rv = ReadTransaction(trans.get(), &response_text);
3827 EXPECT_EQ(OK, rv);
3828 EXPECT_EQ("Payload", response_text);
3829}
3830
3831TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093832 SessionDependencies session_deps(
3833 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353834
3835 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433836 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353837
3838 HttpRequestInfo request;
3839 request.method = "GET";
3840 request.url = GURL("https://www.google.com/");
3841 request.load_flags = 0;
3842
3843 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3844 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373845 const unsigned char kSOCKS5OkRequest[] = {
3846 0x05, // Version
3847 0x01, // Command (CONNECT)
3848 0x00, // Reserved.
3849 0x03, // Address type (DOMAINNAME).
3850 0x0E, // Length of domain (14)
3851 // Domain string:
3852 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3853 0x01, 0xBB, // 16-bit port (443)
3854 };
3855
[email protected]e0c27be2009-07-15 13:09:353856 const char kSOCKS5OkResponse[] =
3857 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3858
3859 MockWrite data_writes[] = {
3860 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3861 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3862 arraysize(kSOCKS5OkRequest)),
3863 MockWrite("GET / HTTP/1.1\r\n"
3864 "Host: www.google.com\r\n"
3865 "Connection: keep-alive\r\n\r\n")
3866 };
3867
3868 MockRead data_reads[] = {
3869 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3870 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023871 MockRead("HTTP/1.0 200 OK\r\n"),
3872 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3873 MockRead("Payload"),
3874 MockRead(false, OK)
3875 };
3876
[email protected]31a2bfe2010-02-09 08:03:393877 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3878 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593879 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023880
[email protected]5ecc992a42009-11-11 01:41:593881 SSLSocketDataProvider ssl(true, OK);
3882 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023883
3884 TestCompletionCallback callback;
3885
[email protected]5a1d7ca2010-04-28 20:12:273886 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023887 EXPECT_EQ(ERR_IO_PENDING, rv);
3888
3889 rv = callback.WaitForResult();
3890 EXPECT_EQ(OK, rv);
3891
3892 const HttpResponseInfo* response = trans->GetResponseInfo();
3893 EXPECT_FALSE(response == NULL);
3894
3895 std::string response_text;
3896 rv = ReadTransaction(trans.get(), &response_text);
3897 EXPECT_EQ(OK, rv);
3898 EXPECT_EQ("Payload", response_text);
3899}
3900
[email protected]04e5be32009-06-26 20:00:313901// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:063902
3903struct GroupNameTest {
3904 std::string proxy_server;
3905 std::string url;
3906 std::string expected_group_name;
3907};
3908
3909scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
3910 const std::string& proxy_server) {
3911 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
3912 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3913
3914 HttpAlternateProtocols* alternate_protocols =
3915 session->mutable_alternate_protocols();
3916 alternate_protocols->SetAlternateProtocolFor(
3917 HostPortPair("host.with.alternate", 80), 443,
3918 HttpAlternateProtocols::NPN_SPDY_1);
3919
3920 return session;
3921}
3922
3923int GroupNameTransactionHelper(
3924 const std::string& url,
3925 const scoped_refptr<HttpNetworkSession>& session) {
3926 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3927
3928 HttpRequestInfo request;
3929 request.method = "GET";
3930 request.url = GURL(url);
3931 request.load_flags = 0;
3932
3933 TestCompletionCallback callback;
3934
3935 // We do not complete this request, the dtor will clean the transaction up.
3936 return trans->Start(&request, &callback, BoundNetLog());
3937}
3938
3939TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
3940 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:313941 {
[email protected]2d731a32010-04-29 01:04:063942 "", // unused
[email protected]04e5be32009-06-26 20:00:313943 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:543944 "www.google.com:80",
3945 },
3946 {
[email protected]2d731a32010-04-29 01:04:063947 "", // unused
[email protected]2ff8b312010-04-26 22:20:543948 "http://[2001:1418:13:1::25]/direct",
3949 "[2001:1418:13:1::25]:80",
[email protected]04e5be32009-06-26 20:00:313950 },
[email protected]04e5be32009-06-26 20:00:313951
3952 // SSL Tests
3953 {
[email protected]2d731a32010-04-29 01:04:063954 "", // unused
[email protected]04e5be32009-06-26 20:00:313955 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:023956 "ssl/www.google.com:443",
[email protected]04e5be32009-06-26 20:00:313957 },
3958 {
[email protected]2d731a32010-04-29 01:04:063959 "", // unused
3960 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:023961 "ssl/[2001:1418:13:1::25]:443",
[email protected]04e5be32009-06-26 20:00:313962 },
3963 {
[email protected]2d731a32010-04-29 01:04:063964 "", // unused
[email protected]2ff8b312010-04-26 22:20:543965 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:023966 "ssl/host.with.alternate:443",
[email protected]2ff8b312010-04-26 22:20:543967 },
[email protected]2d731a32010-04-29 01:04:063968 };
[email protected]2ff8b312010-04-26 22:20:543969
[email protected]2d731a32010-04-29 01:04:063970 HttpNetworkTransaction::SetUseAlternateProtocols(true);
3971
3972 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3973 scoped_refptr<HttpNetworkSession> session(
3974 SetupSessionForGroupNameTests(tests[i].proxy_server));
3975
3976 HttpNetworkSessionPeer peer(session);
3977 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
3978 new CaptureGroupNameTCPSocketPool(session.get()));
3979 peer.SetTCPSocketPool(tcp_conn_pool);
3980
3981 EXPECT_EQ(ERR_IO_PENDING,
3982 GroupNameTransactionHelper(tests[i].url, session));
3983 EXPECT_EQ(tests[i].expected_group_name,
3984 tcp_conn_pool->last_group_name_received());
3985 }
3986
3987 HttpNetworkTransaction::SetUseAlternateProtocols(false);
3988}
3989
3990TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
3991 const GroupNameTest tests[] = {
3992 {
3993 "http_proxy",
3994 "http://www.google.com/http_proxy_normal",
3995 "www.google.com:80",
3996 },
3997
3998 // SSL Tests
3999 {
4000 "http_proxy",
4001 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024002 "ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064003 },
4004
[email protected]9faeded92010-04-29 20:03:054005 {
4006 "http_proxy",
4007 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024008 "ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:054009 },
[email protected]2d731a32010-04-29 01:04:064010 };
4011
4012 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4013
4014 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4015 scoped_refptr<HttpNetworkSession> session(
4016 SetupSessionForGroupNameTests(tests[i].proxy_server));
4017
4018 HttpNetworkSessionPeer peer(session);
4019
4020 scoped_refptr<CaptureGroupNameTCPSocketPool> http_proxy_pool(
4021 new CaptureGroupNameTCPSocketPool(session.get()));
4022 peer.SetSocketPoolForHTTPProxy(
4023 HostPortPair("http_proxy", 80), http_proxy_pool);
4024
4025 EXPECT_EQ(ERR_IO_PENDING,
4026 GroupNameTransactionHelper(tests[i].url, session));
4027 EXPECT_EQ(tests[i].expected_group_name,
4028 http_proxy_pool->last_group_name_received());
4029 }
4030
4031 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4032}
4033
4034TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4035 const GroupNameTest tests[] = {
4036 {
4037 "socks4://socks_proxy:1080",
4038 "http://www.google.com/socks4_direct",
4039 "socks4/www.google.com:80",
4040 },
4041 {
4042 "socks5://socks_proxy:1080",
4043 "http://www.google.com/socks5_direct",
4044 "socks5/www.google.com:80",
4045 },
4046
4047 // SSL Tests
4048 {
4049 "socks4://socks_proxy:1080",
4050 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024051 "socks4/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064052 },
4053 {
4054 "socks5://socks_proxy:1080",
4055 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024056 "socks5/ssl/www.google.com:443",
[email protected]2d731a32010-04-29 01:04:064057 },
4058
[email protected]9faeded92010-04-29 20:03:054059 {
4060 "socks4://socks_proxy:1080",
4061 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024062 "socks4/ssl/host.with.alternate:443",
[email protected]9faeded92010-04-29 20:03:054063 },
[email protected]04e5be32009-06-26 20:00:314064 };
4065
[email protected]2ff8b312010-04-26 22:20:544066 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4067
[email protected]04e5be32009-06-26 20:00:314068 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064069 scoped_refptr<HttpNetworkSession> session(
4070 SetupSessionForGroupNameTests(tests[i].proxy_server));
4071 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314072
[email protected]a796bcec2010-03-22 17:17:264073 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064074 new CaptureGroupNameSOCKSSocketPool(session.get()));
4075 peer.SetSocketPoolForSOCKSProxy(
4076 HostPortPair("socks_proxy", 1080), socks_conn_pool);
[email protected]04e5be32009-06-26 20:00:314077
[email protected]5695b8c2009-09-30 21:36:434078 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314079
[email protected]2d731a32010-04-29 01:04:064080 EXPECT_EQ(ERR_IO_PENDING,
4081 GroupNameTransactionHelper(tests[i].url, session));
4082 EXPECT_EQ(tests[i].expected_group_name,
4083 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314084 }
[email protected]2ff8b312010-04-26 22:20:544085
4086 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:314087}
4088
[email protected]9172a982009-06-06 00:30:254089TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544090 SessionDependencies session_deps(
4091 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324092
[email protected]69719062010-01-05 20:09:214093 // This simulates failure resolving all hostnames; that means we will fail
4094 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324095 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4096
[email protected]9172a982009-06-06 00:30:254097 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434098 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254099
4100 HttpRequestInfo request;
4101 request.method = "GET";
4102 request.url = GURL("http://www.google.com/");
4103
4104 TestCompletionCallback callback;
4105
[email protected]5a1d7ca2010-04-28 20:12:274106 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254107 EXPECT_EQ(ERR_IO_PENDING, rv);
4108
[email protected]9172a982009-06-06 00:30:254109 rv = callback.WaitForResult();
4110 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4111}
4112
[email protected]f3e6c1e2009-06-15 20:52:124113// Host resolution observer used by
4114// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4115// resovle requests are issued with a referrer of |expected_referrer|.
4116class ResolutionReferrerObserver : public HostResolver::Observer {
4117 public:
4118 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4119 : expected_referrer_(expected_referrer),
4120 called_start_with_referrer_(false),
4121 called_finish_with_referrer_(false) {
4122 }
4123
4124 virtual void OnStartResolution(int id,
4125 const HostResolver::RequestInfo& info) {
4126 if (info.referrer() == expected_referrer_)
4127 called_start_with_referrer_ = true;
4128 }
4129
4130 virtual void OnFinishResolutionWithStatus(
4131 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4132 if (info.referrer() == expected_referrer_)
4133 called_finish_with_referrer_ = true;
4134 }
4135
[email protected]eb255d32009-06-17 02:11:034136 virtual void OnCancelResolution(int id,
4137 const HostResolver::RequestInfo& info ) {
4138 FAIL() << "Should not be cancelling any requests!";
4139 }
4140
[email protected]f3e6c1e2009-06-15 20:52:124141 bool did_complete_with_expected_referrer() const {
4142 return called_start_with_referrer_ && called_finish_with_referrer_;
4143 }
4144
4145 private:
4146 GURL expected_referrer_;
4147 bool called_start_with_referrer_;
4148 bool called_finish_with_referrer_;
4149
4150 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4151};
4152
4153// Make sure that when HostResolver::Resolve() is invoked, it passes through
4154// the "referrer". This is depended on by the DNS prefetch observer.
4155TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4156 GURL referrer = GURL("http://expected-referrer/");
4157 EXPECT_TRUE(referrer.is_valid());
4158 ResolutionReferrerObserver resolution_observer(referrer);
4159
4160 SessionDependencies session_deps;
4161 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434162 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124163
4164 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144165 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124166
4167 // Connect up a mock socket which will fail when reading.
4168 MockRead data_reads[] = {
4169 MockRead(false, ERR_FAILED),
4170 };
[email protected]31a2bfe2010-02-09 08:03:394171 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594172 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124173
4174 // Issue a request, containing an HTTP referrer.
4175 HttpRequestInfo request;
4176 request.method = "GET";
4177 request.referrer = referrer;
4178 request.url = GURL("http://www.google.com/");
4179
4180 // Run the request until it fails reading from the socket.
4181 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274182 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124183 EXPECT_EQ(ERR_IO_PENDING, rv);
4184 rv = callback.WaitForResult();
4185 EXPECT_EQ(ERR_FAILED, rv);
4186
4187 // Check that the host resolution observer saw |referrer|.
4188 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4189}
4190
[email protected]685af592010-05-11 19:31:244191// Base test to make sure that when the load flags for a request specify to
4192// bypass the cache, the DNS cache is not used.
4193void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284194 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324195
[email protected]a2c2fb92009-07-18 07:31:044196 // Select a host resolver that does caching.
4197 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324198
[email protected]3b9cca42009-06-16 01:08:284199 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434200 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284201
4202 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4203 // a synchronous lookup.)
4204 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144205 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464206 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274207 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284208 EXPECT_EQ(OK, rv);
4209
4210 // Verify that it was added to host cache, by doing a subsequent async lookup
4211 // and confirming it completes synchronously.
4212 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464213 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284214 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274215 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324216 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284217
4218 // Inject a failure the next time that "www.google.com" is resolved. This way
4219 // we can tell if the next lookup hit the cache, or the "network".
4220 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324221 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284222
4223 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4224 // first read -- this won't be reached as the host resolution will fail first.
4225 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394226 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594227 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284228
4229 // Issue a request, asking to bypass the cache(s).
4230 HttpRequestInfo request;
4231 request.method = "GET";
[email protected]685af592010-05-11 19:31:244232 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284233 request.url = GURL("http://www.google.com/");
4234
4235 // Run the request.
4236 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274237 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284238 ASSERT_EQ(ERR_IO_PENDING, rv);
4239 rv = callback.WaitForResult();
4240
4241 // If we bypassed the cache, we would have gotten a failure while resolving
4242 // "www.google.com".
4243 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4244}
4245
[email protected]685af592010-05-11 19:31:244246// There are multiple load flags that should trigger the host cache bypass.
4247// Test each in isolation:
4248TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4249 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4250}
4251
4252TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4253 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4254}
4255
4256TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
4257 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
4258}
4259
[email protected]0877e3d2009-10-17 22:29:574260// Make sure we can handle an error when writing the request.
4261TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4262 SessionDependencies session_deps;
4263 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4264
4265 HttpRequestInfo request;
4266 request.method = "GET";
4267 request.url = GURL("http://www.foo.com/");
4268 request.load_flags = 0;
4269
4270 MockWrite write_failure[] = {
4271 MockWrite(true, ERR_CONNECTION_RESET),
4272 };
[email protected]31a2bfe2010-02-09 08:03:394273 StaticSocketDataProvider data(NULL, 0,
4274 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594275 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574276
4277 TestCompletionCallback callback;
4278
4279 scoped_ptr<HttpTransaction> trans(
4280 new HttpNetworkTransaction(CreateSession(&session_deps)));
4281
[email protected]5a1d7ca2010-04-28 20:12:274282 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574283 EXPECT_EQ(ERR_IO_PENDING, rv);
4284
4285 rv = callback.WaitForResult();
4286 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4287}
4288
4289// Check that a connection closed after the start of the headers finishes ok.
4290TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4291 SessionDependencies session_deps;
4292 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4293
4294 HttpRequestInfo request;
4295 request.method = "GET";
4296 request.url = GURL("http://www.foo.com/");
4297 request.load_flags = 0;
4298
4299 MockRead data_reads[] = {
4300 MockRead("HTTP/1."),
4301 MockRead(false, OK),
4302 };
4303
[email protected]31a2bfe2010-02-09 08:03:394304 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594305 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574306
4307 TestCompletionCallback callback;
4308
4309 scoped_ptr<HttpTransaction> trans(
4310 new HttpNetworkTransaction(CreateSession(&session_deps)));
4311
[email protected]5a1d7ca2010-04-28 20:12:274312 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574313 EXPECT_EQ(ERR_IO_PENDING, rv);
4314
4315 rv = callback.WaitForResult();
4316 EXPECT_EQ(OK, rv);
4317
4318 const HttpResponseInfo* response = trans->GetResponseInfo();
4319 EXPECT_TRUE(response != NULL);
4320
4321 EXPECT_TRUE(response->headers != NULL);
4322 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4323
4324 std::string response_data;
4325 rv = ReadTransaction(trans.get(), &response_data);
4326 EXPECT_EQ(OK, rv);
4327 EXPECT_EQ("", response_data);
4328}
4329
4330// Make sure that a dropped connection while draining the body for auth
4331// restart does the right thing.
4332TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4333 SessionDependencies session_deps;
4334 scoped_ptr<HttpTransaction> trans(
4335 new HttpNetworkTransaction(CreateSession(&session_deps)));
4336
4337 HttpRequestInfo request;
4338 request.method = "GET";
4339 request.url = GURL("http://www.google.com/");
4340 request.load_flags = 0;
4341
4342 MockWrite data_writes1[] = {
4343 MockWrite("GET / HTTP/1.1\r\n"
4344 "Host: www.google.com\r\n"
4345 "Connection: keep-alive\r\n\r\n"),
4346 };
4347
4348 MockRead data_reads1[] = {
4349 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4350 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4351 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4352 MockRead("Content-Length: 14\r\n\r\n"),
4353 MockRead("Unauth"),
4354 MockRead(true, ERR_CONNECTION_RESET),
4355 };
4356
[email protected]31a2bfe2010-02-09 08:03:394357 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4358 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594359 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574360
4361 // After calling trans->RestartWithAuth(), this is the request we should
4362 // be issuing -- the final header line contains the credentials.
4363 MockWrite data_writes2[] = {
4364 MockWrite("GET / HTTP/1.1\r\n"
4365 "Host: www.google.com\r\n"
4366 "Connection: keep-alive\r\n"
4367 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4368 };
4369
4370 // Lastly, the server responds with the actual content.
4371 MockRead data_reads2[] = {
4372 MockRead("HTTP/1.1 200 OK\r\n"),
4373 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4374 MockRead("Content-Length: 100\r\n\r\n"),
4375 MockRead(false, OK),
4376 };
4377
[email protected]31a2bfe2010-02-09 08:03:394378 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4379 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594380 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574381
4382 TestCompletionCallback callback1;
4383
[email protected]5a1d7ca2010-04-28 20:12:274384 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574385 EXPECT_EQ(ERR_IO_PENDING, rv);
4386
4387 rv = callback1.WaitForResult();
4388 EXPECT_EQ(OK, rv);
4389
4390 const HttpResponseInfo* response = trans->GetResponseInfo();
4391 EXPECT_FALSE(response == NULL);
4392
4393 // The password prompt info should have been set in response->auth_challenge.
4394 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4395
4396 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4397 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4398 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4399
4400 TestCompletionCallback callback2;
4401
4402 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4403 EXPECT_EQ(ERR_IO_PENDING, rv);
4404
4405 rv = callback2.WaitForResult();
4406 EXPECT_EQ(OK, rv);
4407
4408 response = trans->GetResponseInfo();
4409 EXPECT_FALSE(response == NULL);
4410 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4411 EXPECT_EQ(100, response->headers->GetContentLength());
4412}
4413
4414// Test HTTPS connections going through a proxy that sends extra data.
4415TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4416 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4417
4418 HttpRequestInfo request;
4419 request.method = "GET";
4420 request.url = GURL("https://www.google.com/");
4421 request.load_flags = 0;
4422
4423 MockRead proxy_reads[] = {
4424 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4425 MockRead(false, OK)
4426 };
4427
[email protected]31a2bfe2010-02-09 08:03:394428 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594429 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574430
[email protected]5ecc992a42009-11-11 01:41:594431 session_deps.socket_factory.AddSocketDataProvider(&data);
4432 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574433
4434 TestCompletionCallback callback;
4435
4436 session_deps.socket_factory.ResetNextMockIndexes();
4437
4438 scoped_ptr<HttpTransaction> trans(
4439 new HttpNetworkTransaction(CreateSession(&session_deps)));
4440
[email protected]5a1d7ca2010-04-28 20:12:274441 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574442 EXPECT_EQ(ERR_IO_PENDING, rv);
4443
4444 rv = callback.WaitForResult();
4445 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4446}
4447
[email protected]e22e1362009-11-23 21:31:124448TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464449 SessionDependencies session_deps;
4450 scoped_ptr<HttpTransaction> trans(
4451 new HttpNetworkTransaction(CreateSession(&session_deps)));
4452
4453 HttpRequestInfo request;
4454 request.method = "GET";
4455 request.url = GURL("http://www.google.com/");
4456 request.load_flags = 0;
4457
[email protected]e22e1362009-11-23 21:31:124458 MockRead data_reads[] = {
4459 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4460 MockRead(false, OK),
4461 };
[email protected]9492e4a2010-02-24 00:58:464462
4463 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4464 session_deps.socket_factory.AddSocketDataProvider(&data);
4465
4466 TestCompletionCallback callback;
4467
[email protected]5a1d7ca2010-04-28 20:12:274468 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464469 EXPECT_EQ(ERR_IO_PENDING, rv);
4470
4471 EXPECT_EQ(OK, callback.WaitForResult());
4472
4473 const HttpResponseInfo* response = trans->GetResponseInfo();
4474 EXPECT_TRUE(response != NULL);
4475
4476 EXPECT_TRUE(response->headers != NULL);
4477 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4478
4479 std::string response_data;
4480 rv = ReadTransaction(trans.get(), &response_data);
4481 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124482}
4483
[email protected]95d88ffe2010-02-04 21:25:334484TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4485 SessionDependencies session_deps;
4486 scoped_ptr<HttpTransaction> trans(
4487 new HttpNetworkTransaction(CreateSession(&session_deps)));
4488
4489 HttpRequestInfo request;
4490 request.method = "POST";
4491 request.url = GURL("http://www.google.com/upload");
4492 request.upload_data = new UploadData;
4493 request.load_flags = 0;
4494
4495 FilePath temp_file_path;
4496 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4497 const uint64 kFakeSize = 100000; // file is actually blank
4498
4499 std::vector<UploadData::Element> elements;
4500 UploadData::Element element;
4501 element.SetToFilePath(temp_file_path);
4502 element.SetContentLength(kFakeSize);
4503 elements.push_back(element);
4504 request.upload_data->set_elements(elements);
4505 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4506
4507 MockRead data_reads[] = {
4508 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4509 MockRead("hello world"),
4510 MockRead(false, OK),
4511 };
[email protected]31a2bfe2010-02-09 08:03:394512 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334513 session_deps.socket_factory.AddSocketDataProvider(&data);
4514
4515 TestCompletionCallback callback;
4516
[email protected]5a1d7ca2010-04-28 20:12:274517 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334518 EXPECT_EQ(ERR_IO_PENDING, rv);
4519
4520 rv = callback.WaitForResult();
4521 EXPECT_EQ(OK, rv);
4522
4523 const HttpResponseInfo* response = trans->GetResponseInfo();
4524 EXPECT_TRUE(response != NULL);
4525
4526 EXPECT_TRUE(response->headers != NULL);
4527 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4528
4529 std::string response_data;
4530 rv = ReadTransaction(trans.get(), &response_data);
4531 EXPECT_EQ(OK, rv);
4532 EXPECT_EQ("hello world", response_data);
4533
4534 file_util::Delete(temp_file_path, false);
4535}
4536
[email protected]6624b4622010-03-29 19:58:364537TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4538 // If we try to upload an unreadable file, the network stack should report
4539 // the file size as zero and upload zero bytes for that file.
4540 SessionDependencies session_deps;
4541 scoped_ptr<HttpTransaction> trans(
4542 new HttpNetworkTransaction(CreateSession(&session_deps)));
4543
4544 FilePath temp_file;
4545 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4546 std::string temp_file_content("Unreadable file.");
4547 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4548 temp_file_content.length()));
4549 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4550
4551 HttpRequestInfo request;
4552 request.method = "POST";
4553 request.url = GURL("http://www.google.com/upload");
4554 request.upload_data = new UploadData;
4555 request.load_flags = 0;
4556
4557 std::vector<UploadData::Element> elements;
4558 UploadData::Element element;
4559 element.SetToFilePath(temp_file);
4560 elements.push_back(element);
4561 request.upload_data->set_elements(elements);
4562
4563 MockRead data_reads[] = {
4564 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4565 MockRead(false, OK),
4566 };
4567 MockWrite data_writes[] = {
4568 MockWrite("POST /upload HTTP/1.1\r\n"
4569 "Host: www.google.com\r\n"
4570 "Connection: keep-alive\r\n"
4571 "Content-Length: 0\r\n\r\n"),
4572 MockWrite(false, OK),
4573 };
4574 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4575 arraysize(data_writes));
4576 session_deps.socket_factory.AddSocketDataProvider(&data);
4577
4578 TestCompletionCallback callback;
4579
[email protected]5a1d7ca2010-04-28 20:12:274580 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364581 EXPECT_EQ(ERR_IO_PENDING, rv);
4582
4583 rv = callback.WaitForResult();
4584 EXPECT_EQ(OK, rv);
4585
4586 const HttpResponseInfo* response = trans->GetResponseInfo();
4587 EXPECT_TRUE(response != NULL);
4588 EXPECT_TRUE(response->headers != NULL);
4589 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4590
4591 file_util::Delete(temp_file, false);
4592}
4593
4594TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4595 SessionDependencies session_deps;
4596 scoped_ptr<HttpTransaction> trans(
4597 new HttpNetworkTransaction(CreateSession(&session_deps)));
4598
4599 FilePath temp_file;
4600 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4601 std::string temp_file_contents("Unreadable file.");
4602 std::string unreadable_contents(temp_file_contents.length(), '\0');
4603 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4604 temp_file_contents.length()));
4605
4606 HttpRequestInfo request;
4607 request.method = "POST";
4608 request.url = GURL("http://www.google.com/upload");
4609 request.upload_data = new UploadData;
4610 request.load_flags = 0;
4611
4612 std::vector<UploadData::Element> elements;
4613 UploadData::Element element;
4614 element.SetToFilePath(temp_file);
4615 elements.push_back(element);
4616 request.upload_data->set_elements(elements);
4617
4618 MockRead data_reads[] = {
4619 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4620 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4621 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4622
4623 MockRead("HTTP/1.1 200 OK\r\n"),
4624 MockRead("Content-Length: 0\r\n\r\n"),
4625 MockRead(false, OK),
4626 };
4627 MockWrite data_writes[] = {
4628 MockWrite("POST /upload HTTP/1.1\r\n"
4629 "Host: www.google.com\r\n"
4630 "Connection: keep-alive\r\n"
4631 "Content-Length: 16\r\n\r\n"),
4632 MockWrite(false, temp_file_contents.c_str()),
4633
4634 MockWrite("POST /upload HTTP/1.1\r\n"
4635 "Host: www.google.com\r\n"
4636 "Connection: keep-alive\r\n"
4637 "Content-Length: 16\r\n"
4638 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4639 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4640 MockWrite(false, OK),
4641 };
4642 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4643 arraysize(data_writes));
4644 session_deps.socket_factory.AddSocketDataProvider(&data);
4645
4646 TestCompletionCallback callback1;
4647
[email protected]5a1d7ca2010-04-28 20:12:274648 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364649 EXPECT_EQ(ERR_IO_PENDING, rv);
4650
4651 rv = callback1.WaitForResult();
4652 EXPECT_EQ(OK, rv);
4653
4654 const HttpResponseInfo* response = trans->GetResponseInfo();
4655 EXPECT_TRUE(response != NULL);
4656 EXPECT_TRUE(response->headers != NULL);
4657 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4658
4659 // The password prompt info should have been set in response->auth_challenge.
4660 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4661 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4662 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4663 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4664
4665 // Now make the file unreadable and try again.
4666 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4667
4668 TestCompletionCallback callback2;
4669
4670 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4671 EXPECT_EQ(ERR_IO_PENDING, rv);
4672
4673 rv = callback2.WaitForResult();
4674 EXPECT_EQ(OK, rv);
4675
4676 response = trans->GetResponseInfo();
4677 EXPECT_TRUE(response != NULL);
4678 EXPECT_TRUE(response->headers != NULL);
4679 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4680 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4681
4682 file_util::Delete(temp_file, false);
4683}
4684
[email protected]aeefc9e82010-02-19 16:18:274685// Tests that changes to Auth realms are treated like auth rejections.
4686TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4687 SessionDependencies session_deps;
4688 scoped_ptr<HttpTransaction> trans(
4689 new HttpNetworkTransaction(CreateSession(&session_deps)));
4690
4691 HttpRequestInfo request;
4692 request.method = "GET";
4693 request.url = GURL("http://www.google.com/");
4694 request.load_flags = 0;
4695
4696 // First transaction will request a resource and receive a Basic challenge
4697 // with realm="first_realm".
4698 MockWrite data_writes1[] = {
4699 MockWrite("GET / HTTP/1.1\r\n"
4700 "Host: www.google.com\r\n"
4701 "Connection: keep-alive\r\n"
4702 "\r\n"),
4703 };
4704 MockRead data_reads1[] = {
4705 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4706 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4707 "\r\n"),
4708 };
4709
4710 // After calling trans->RestartWithAuth(), provide an Authentication header
4711 // for first_realm. The server will reject and provide a challenge with
4712 // second_realm.
4713 MockWrite data_writes2[] = {
4714 MockWrite("GET / HTTP/1.1\r\n"
4715 "Host: www.google.com\r\n"
4716 "Connection: keep-alive\r\n"
4717 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4718 "\r\n"),
4719 };
4720 MockRead data_reads2[] = {
4721 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4722 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4723 "\r\n"),
4724 };
4725
4726 // This again fails, and goes back to first_realm. Make sure that the
4727 // entry is removed from cache.
4728 MockWrite data_writes3[] = {
4729 MockWrite("GET / HTTP/1.1\r\n"
4730 "Host: www.google.com\r\n"
4731 "Connection: keep-alive\r\n"
4732 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4733 "\r\n"),
4734 };
4735 MockRead data_reads3[] = {
4736 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4737 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4738 "\r\n"),
4739 };
4740
4741 // Try one last time (with the correct password) and get the resource.
4742 MockWrite data_writes4[] = {
4743 MockWrite("GET / HTTP/1.1\r\n"
4744 "Host: www.google.com\r\n"
4745 "Connection: keep-alive\r\n"
4746 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4747 "\r\n"),
4748 };
4749 MockRead data_reads4[] = {
4750 MockRead("HTTP/1.1 200 OK\r\n"
4751 "Content-Type: text/html; charset=iso-8859-1\r\n"
4752 "Content-Length: 100\r\n"
4753 "\r\n"),
4754 };
4755
4756 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4757 data_writes1, arraysize(data_writes1));
4758 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4759 data_writes2, arraysize(data_writes2));
4760 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4761 data_writes3, arraysize(data_writes3));
4762 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4763 data_writes4, arraysize(data_writes4));
4764 session_deps.socket_factory.AddSocketDataProvider(&data1);
4765 session_deps.socket_factory.AddSocketDataProvider(&data2);
4766 session_deps.socket_factory.AddSocketDataProvider(&data3);
4767 session_deps.socket_factory.AddSocketDataProvider(&data4);
4768
4769 TestCompletionCallback callback1;
4770
4771 // Issue the first request with Authorize headers. There should be a
4772 // password prompt for first_realm waiting to be filled in after the
4773 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:274774 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:274775 EXPECT_EQ(ERR_IO_PENDING, rv);
4776 rv = callback1.WaitForResult();
4777 EXPECT_EQ(OK, rv);
4778 const HttpResponseInfo* response = trans->GetResponseInfo();
4779 ASSERT_FALSE(response == NULL);
4780 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4781 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4782 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4783 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4784
4785 // Issue the second request with an incorrect password. There should be a
4786 // password prompt for second_realm waiting to be filled in after the
4787 // transaction completes.
4788 TestCompletionCallback callback2;
4789 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4790 EXPECT_EQ(ERR_IO_PENDING, rv);
4791 rv = callback2.WaitForResult();
4792 EXPECT_EQ(OK, rv);
4793 response = trans->GetResponseInfo();
4794 ASSERT_FALSE(response == NULL);
4795 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4796 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4797 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4798 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4799
4800 // Issue the third request with another incorrect password. There should be
4801 // a password prompt for first_realm waiting to be filled in. If the password
4802 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4803 // first_realm was not correctly removed.
4804 TestCompletionCallback callback3;
4805 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4806 EXPECT_EQ(ERR_IO_PENDING, rv);
4807 rv = callback3.WaitForResult();
4808 EXPECT_EQ(OK, rv);
4809 response = trans->GetResponseInfo();
4810 ASSERT_FALSE(response == NULL);
4811 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4812 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4813 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4814 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4815
4816 // Issue the fourth request with the correct password and username.
4817 TestCompletionCallback callback4;
4818 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4819 EXPECT_EQ(ERR_IO_PENDING, rv);
4820 rv = callback4.WaitForResult();
4821 EXPECT_EQ(OK, rv);
4822 response = trans->GetResponseInfo();
4823 ASSERT_FALSE(response == NULL);
4824 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4825}
4826
[email protected]564b4912010-03-09 16:30:424827TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424828 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:064829 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:424830
[email protected]564b4912010-03-09 16:30:424831 SessionDependencies session_deps;
4832
4833 MockRead data_reads[] = {
4834 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]31e2c69e2010-04-15 18:06:064835 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424836 MockRead("hello world"),
4837 MockRead(false, OK),
4838 };
4839
4840 HttpRequestInfo request;
4841 request.method = "GET";
4842 request.url = GURL("http://www.google.com/");
4843 request.load_flags = 0;
4844
4845 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4846
4847 session_deps.socket_factory.AddSocketDataProvider(&data);
4848
4849 TestCompletionCallback callback;
4850
4851 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4852 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4853
[email protected]5a1d7ca2010-04-28 20:12:274854 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424855 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534856
[email protected]564b4912010-03-09 16:30:424857 HostPortPair http_host_port_pair;
4858 http_host_port_pair.host = "www.google.com";
4859 http_host_port_pair.port = 80;
4860 const HttpAlternateProtocols& alternate_protocols =
4861 session->alternate_protocols();
4862 EXPECT_FALSE(
4863 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4864
4865 EXPECT_EQ(OK, callback.WaitForResult());
4866
4867 const HttpResponseInfo* response = trans->GetResponseInfo();
4868 ASSERT_TRUE(response != NULL);
4869 ASSERT_TRUE(response->headers != NULL);
4870 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:534871 EXPECT_FALSE(response->was_fetched_via_spdy);
4872 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:424873
4874 std::string response_data;
4875 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4876 EXPECT_EQ("hello world", response_data);
4877
4878 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4879 const HttpAlternateProtocols::PortProtocolPair alternate =
4880 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4881 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4882 expected_alternate.port = 443;
[email protected]31e2c69e2010-04-15 18:06:064883 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_1;
[email protected]564b4912010-03-09 16:30:424884 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:424885
[email protected]31e2c69e2010-04-15 18:06:064886 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:424887 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:424888}
4889
4890TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:064891 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:424892 SessionDependencies session_deps;
4893
4894 HttpRequestInfo request;
4895 request.method = "GET";
4896 request.url = GURL("http://www.google.com/");
4897 request.load_flags = 0;
4898
4899 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4900 StaticSocketDataProvider first_data;
4901 first_data.set_connect_data(mock_connect);
4902 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4903
4904 MockRead data_reads[] = {
4905 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4906 MockRead("hello world"),
4907 MockRead(true, OK),
4908 };
4909 StaticSocketDataProvider second_data(
4910 data_reads, arraysize(data_reads), NULL, 0);
4911 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4912
4913 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4914 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4915 // http://crbug.com/37454.
4916 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4917
4918 TestCompletionCallback callback;
4919
4920 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4921
4922 HostPortPair http_host_port_pair;
4923 http_host_port_pair.host = "www.google.com";
4924 http_host_port_pair.port = 80;
4925 HttpAlternateProtocols* alternate_protocols =
4926 session->mutable_alternate_protocols();
4927 alternate_protocols->SetAlternateProtocolFor(
4928 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]31e2c69e2010-04-15 18:06:064929 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:424930
4931 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4932
[email protected]5a1d7ca2010-04-28 20:12:274933 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424934 EXPECT_EQ(ERR_IO_PENDING, rv);
4935 EXPECT_EQ(OK, callback.WaitForResult());
4936
4937 const HttpResponseInfo* response = trans->GetResponseInfo();
4938 ASSERT_TRUE(response != NULL);
4939 ASSERT_TRUE(response->headers != NULL);
4940 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4941
4942 std::string response_data;
4943 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4944 EXPECT_EQ("hello world", response_data);
4945
4946 ASSERT_TRUE(
4947 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
4948 const HttpAlternateProtocols::PortProtocolPair alternate =
4949 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
4950 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:064951 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:424952}
4953
4954// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
4955// says that it does SPDY, but it just does the TLS handshake, but the NPN
4956// response does not indicate SPDY, so we just do standard HTTPS over the port.
4957// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
4958// on the original port.
[email protected]a2cb8122010-03-10 17:22:424959// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
4960// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:534961//
[email protected]a2cb8122010-03-10 17:22:424962// HttpRequestInfo request;
4963// request.method = "GET";
4964// request.url = GURL("http://www.google.com/");
4965// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:534966//
[email protected]a2cb8122010-03-10 17:22:424967// MockRead data_reads[] = {
4968// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4969// MockRead("hello world"),
4970// MockRead(true, OK),
4971// };
4972// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4973// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:534974//
[email protected]a2cb8122010-03-10 17:22:424975// SSLSocketDataProvider ssl(true, OK);
4976// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:534977//
[email protected]a2cb8122010-03-10 17:22:424978// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:534979//
[email protected]a2cb8122010-03-10 17:22:424980// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:534981//
[email protected]a2cb8122010-03-10 17:22:424982// HostPortPair http_host_port_pair;
4983// http_host_port_pair.host = "www.google.com";
4984// http_host_port_pair.port = 80;
4985// HttpAlternateProtocols* alternate_protocols =
4986// session->mutable_alternate_protocols();
4987// alternate_protocols->SetAlternateProtocolFor(
4988// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:064989// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:534990//
[email protected]a2cb8122010-03-10 17:22:424991// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:534992//
[email protected]5a1d7ca2010-04-28 20:12:274993// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:424994// EXPECT_EQ(ERR_IO_PENDING, rv);
4995// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:534996//
[email protected]a2cb8122010-03-10 17:22:424997// const HttpResponseInfo* response = trans->GetResponseInfo();
4998// ASSERT_TRUE(response != NULL);
4999// ASSERT_TRUE(response->headers != NULL);
5000// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535001//
[email protected]a2cb8122010-03-10 17:22:425002// std::string response_data;
5003// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5004// EXPECT_EQ("hello world", response_data);
5005// }
5006
5007TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:065008 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]2ff8b312010-04-26 22:20:545009 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115010 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]564b4912010-03-09 16:30:425011 SessionDependencies session_deps;
5012
5013 HttpRequestInfo request;
5014 request.method = "GET";
5015 request.url = GURL("http://www.google.com/");
5016 request.load_flags = 0;
5017
[email protected]a2cb8122010-03-10 17:22:425018 StaticSocketDataProvider first_tcp_connect;
5019 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5020
5021 SSLSocketDataProvider ssl(true, OK);
5022 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5023
[email protected]564b4912010-03-09 16:30:425024 MockRead data_reads[] = {
5025 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5026 MockRead("hello world"),
5027 MockRead(true, OK),
5028 };
[email protected]a2cb8122010-03-10 17:22:425029 StaticSocketDataProvider fallback_data(
5030 data_reads, arraysize(data_reads), NULL, 0);
5031 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425032
5033 TestCompletionCallback callback;
5034
5035 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5036
5037 HostPortPair http_host_port_pair;
5038 http_host_port_pair.host = "www.google.com";
5039 http_host_port_pair.port = 80;
5040 HttpAlternateProtocols* alternate_protocols =
5041 session->mutable_alternate_protocols();
5042 alternate_protocols->SetAlternateProtocolFor(
5043 http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065044 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:425045
5046 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5047
[email protected]5a1d7ca2010-04-28 20:12:275048 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425049 EXPECT_EQ(ERR_IO_PENDING, rv);
5050 EXPECT_EQ(OK, callback.WaitForResult());
5051
5052 const HttpResponseInfo* response = trans->GetResponseInfo();
5053 ASSERT_TRUE(response != NULL);
5054 ASSERT_TRUE(response->headers != NULL);
5055 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5056
5057 std::string response_data;
5058 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5059 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:545060 HttpNetworkTransaction::SetNextProtos("");
5061 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5062}
5063
5064TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
5065 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5066 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115067 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545068 SessionDependencies session_deps;
5069
5070 HttpRequestInfo request;
5071 request.method = "GET";
5072 request.url = GURL("http://www.google.com/");
5073 request.load_flags = 0;
5074
5075 MockRead data_reads[] = {
5076 MockRead("HTTP/1.1 200 OK\r\n"),
5077 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5078 MockRead("hello world"),
5079 MockRead(true, OK),
5080 };
5081
5082 StaticSocketDataProvider first_transaction(
5083 data_reads, arraysize(data_reads), NULL, 0);
5084 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5085
5086 SSLSocketDataProvider ssl(true, OK);
5087 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5088 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535089 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545090 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5091
5092 MockWrite spdy_writes[] = {
5093 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
5094 arraysize(kGetSyn)),
5095 };
5096
5097 MockRead spdy_reads[] = {
5098 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
5099 arraysize(kGetSynReply)),
5100 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
5101 arraysize(kGetBodyFrame)),
5102 MockRead(true, 0, 0),
5103 };
5104
5105 scoped_refptr<DelayedSocketData> spdy_data(
5106 new DelayedSocketData(
5107 1, // wait for one write to finish before reading.
5108 spdy_reads, arraysize(spdy_reads),
5109 spdy_writes, arraysize(spdy_writes)));
5110 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5111
5112 TestCompletionCallback callback;
5113
5114 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5115 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5116
[email protected]5a1d7ca2010-04-28 20:12:275117 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545118 EXPECT_EQ(ERR_IO_PENDING, rv);
5119 EXPECT_EQ(OK, callback.WaitForResult());
5120
5121 const HttpResponseInfo* response = trans->GetResponseInfo();
5122 ASSERT_TRUE(response != NULL);
5123 ASSERT_TRUE(response->headers != NULL);
5124 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5125
5126 std::string response_data;
5127 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5128 EXPECT_EQ("hello world", response_data);
5129
5130 trans.reset(new HttpNetworkTransaction(session));
5131
[email protected]5a1d7ca2010-04-28 20:12:275132 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545133 EXPECT_EQ(ERR_IO_PENDING, rv);
5134 EXPECT_EQ(OK, callback.WaitForResult());
5135
5136 response = trans->GetResponseInfo();
5137 ASSERT_TRUE(response != NULL);
5138 ASSERT_TRUE(response->headers != NULL);
5139 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535140 EXPECT_TRUE(response->was_fetched_via_spdy);
5141 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:545142
5143 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5144 EXPECT_EQ("hello!", response_data);
5145
5146 HttpNetworkTransaction::SetNextProtos("");
5147 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5148}
5149
[email protected]631f1322010-04-30 17:59:115150class CapturingProxyResolver : public ProxyResolver {
5151 public:
5152 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5153 virtual ~CapturingProxyResolver() {}
5154
5155 virtual int GetProxyForURL(const GURL& url,
5156 ProxyInfo* results,
5157 CompletionCallback* callback,
5158 RequestHandle* request,
5159 const BoundNetLog& net_log) {
[email protected]d911f1b2010-05-05 22:39:425160 ProxyServer proxy_server(
5161 ProxyServer::SCHEME_HTTP, "myproxy", 80);
5162 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115163 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425164 return OK;
[email protected]631f1322010-04-30 17:59:115165 }
5166
5167 virtual void CancelRequest(RequestHandle request) {
5168 NOTREACHED();
5169 }
5170
5171 const std::vector<GURL>& resolved() const { return resolved_; }
5172
5173 private:
5174 virtual int SetPacScript(const GURL& /*pac_url*/,
5175 const std::string& /*pac_bytes*/,
5176 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425177 return OK;
[email protected]631f1322010-04-30 17:59:115178 }
5179
5180 std::vector<GURL> resolved_;
5181
5182 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5183};
5184
[email protected]631f1322010-04-30 17:59:115185TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
5186 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5187 HttpNetworkTransaction::SetNextProtos(
5188 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
5189
5190 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425191 proxy_config.set_auto_detect(true);
5192 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115193
[email protected]631f1322010-04-30 17:59:115194 CapturingProxyResolver* capturing_proxy_resolver =
5195 new CapturingProxyResolver();
5196 SessionDependencies session_deps(
5197 new ProxyService(new ProxyConfigServiceFixed(proxy_config),
5198 capturing_proxy_resolver,
5199 NULL,
5200 NULL));
5201
5202 HttpRequestInfo request;
5203 request.method = "GET";
5204 request.url = GURL("http://www.google.com/");
5205 request.load_flags = 0;
5206
5207 MockRead data_reads[] = {
5208 MockRead("HTTP/1.1 200 OK\r\n"),
5209 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5210 MockRead("hello world"),
5211 MockRead(true, OK),
5212 };
5213
5214 StaticSocketDataProvider first_transaction(
5215 data_reads, arraysize(data_reads), NULL, 0);
5216 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5217
5218 SSLSocketDataProvider ssl(true, OK);
5219 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5220 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535221 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:115222 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5223
5224 MockWrite spdy_writes[] = {
5225 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5226 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425227 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]631f1322010-04-30 17:59:115228 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
[email protected]d911f1b2010-05-05 22:39:425229 arraysize(kGetSyn)), // 3
[email protected]631f1322010-04-30 17:59:115230 };
5231
[email protected]d911f1b2010-05-05 22:39:425232 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5233
[email protected]631f1322010-04-30 17:59:115234 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425235 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
5236 MockRead(true, reinterpret_cast<const char*>(kGetSynReply), // 2, 4
5237 arraysize(kGetSynReply), 4),
5238 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame), // 5
5239 arraysize(kGetBodyFrame), 4),
5240 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115241 };
5242
[email protected]d911f1b2010-05-05 22:39:425243 scoped_refptr<OrderedSocketData> spdy_data(
5244 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115245 spdy_reads, arraysize(spdy_reads),
5246 spdy_writes, arraysize(spdy_writes)));
5247 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5248
5249 TestCompletionCallback callback;
5250
5251 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5252 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5253
5254 int rv = trans->Start(&request, &callback, BoundNetLog());
5255 EXPECT_EQ(ERR_IO_PENDING, rv);
5256 EXPECT_EQ(OK, callback.WaitForResult());
5257
5258 const HttpResponseInfo* response = trans->GetResponseInfo();
5259 ASSERT_TRUE(response != NULL);
5260 ASSERT_TRUE(response->headers != NULL);
5261 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535262 EXPECT_FALSE(response->was_fetched_via_spdy);
5263 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115264
5265 std::string response_data;
5266 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5267 EXPECT_EQ("hello world", response_data);
5268
5269 trans.reset(new HttpNetworkTransaction(session));
5270
5271 rv = trans->Start(&request, &callback, BoundNetLog());
5272 EXPECT_EQ(ERR_IO_PENDING, rv);
5273 EXPECT_EQ(OK, callback.WaitForResult());
5274
5275 response = trans->GetResponseInfo();
5276 ASSERT_TRUE(response != NULL);
5277 ASSERT_TRUE(response->headers != NULL);
5278 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535279 EXPECT_TRUE(response->was_fetched_via_spdy);
5280 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115281
5282 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5283 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425284 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5285 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115286 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425287 EXPECT_EQ("https://www.google.com/",
5288 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115289
5290 HttpNetworkTransaction::SetNextProtos("");
5291 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5292}
[email protected]631f1322010-04-30 17:59:115293
[email protected]2ff8b312010-04-26 22:20:545294TEST_F(HttpNetworkTransactionTest,
5295 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5296 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5297 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115298 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545299 SessionDependencies session_deps;
5300
5301 HttpRequestInfo request;
5302 request.method = "GET";
5303 request.url = GURL("http://www.google.com/");
5304 request.load_flags = 0;
5305
5306 MockRead data_reads[] = {
5307 MockRead("HTTP/1.1 200 OK\r\n"),
5308 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5309 MockRead("hello world"),
5310 MockRead(true, OK),
5311 };
5312
5313 StaticSocketDataProvider first_transaction(
5314 data_reads, arraysize(data_reads), NULL, 0);
5315 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5316
5317 SSLSocketDataProvider ssl(true, OK);
5318 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5319 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535320 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545321 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:535322 // Make sure we use ssl for spdy here.
5323 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:545324
5325 MockWrite spdy_writes[] = {
5326 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
5327 arraysize(kGetSyn)),
5328 };
5329
5330 MockRead spdy_reads[] = {
5331 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
5332 arraysize(kGetSynReply)),
5333 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
5334 arraysize(kGetBodyFrame)),
5335 MockRead(true, 0, 0),
5336 };
5337
5338 scoped_refptr<DelayedSocketData> spdy_data(
5339 new DelayedSocketData(
5340 1, // wait for one write to finish before reading.
5341 spdy_reads, arraysize(spdy_reads),
5342 spdy_writes, arraysize(spdy_writes)));
5343 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5344
5345 TestCompletionCallback callback;
5346
5347 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5348
5349 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5350
[email protected]5a1d7ca2010-04-28 20:12:275351 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545352 EXPECT_EQ(ERR_IO_PENDING, rv);
5353 EXPECT_EQ(OK, callback.WaitForResult());
5354
5355 const HttpResponseInfo* response = trans->GetResponseInfo();
5356 ASSERT_TRUE(response != NULL);
5357 ASSERT_TRUE(response->headers != NULL);
5358 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5359
5360 std::string response_data;
5361 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5362 EXPECT_EQ("hello world", response_data);
5363
5364 // Set up an initial SpdySession in the pool to reuse.
5365 scoped_refptr<SpdySession> spdy_session =
5366 session->spdy_session_pool()->Get(HostPortPair("www.google.com", 443),
[email protected]635909f2010-05-12 18:19:365367 session, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545368 TCPSocketParams tcp_params("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:365369 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:545370 trans.reset(new HttpNetworkTransaction(session));
5371
[email protected]5a1d7ca2010-04-28 20:12:275372 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545373 EXPECT_EQ(ERR_IO_PENDING, rv);
5374 EXPECT_EQ(OK, callback.WaitForResult());
5375
5376 response = trans->GetResponseInfo();
5377 ASSERT_TRUE(response != NULL);
5378 ASSERT_TRUE(response->headers != NULL);
5379 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535380 EXPECT_TRUE(response->was_fetched_via_spdy);
5381 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:545382
5383 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5384 EXPECT_EQ("hello!", response_data);
5385
5386 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065387 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425388}
5389
[email protected]e5ae96a2010-04-14 20:12:455390// MockAuthHandlerCanonical is used by the ResolveCanonicalName
5391// HttpNetworkTransaction unit test below. Callers set up expectations for
5392// whether the canonical name needs to be resolved.
5393class MockAuthHandlerCanonical : public HttpAuthHandler {
5394 public:
5395 enum Resolve {
5396 RESOLVE_INIT,
5397 RESOLVE_SKIP,
5398 RESOLVE_SYNC,
5399 RESOLVE_ASYNC,
5400 RESOLVE_TESTED,
5401 };
5402
5403 MockAuthHandlerCanonical() : resolve_(RESOLVE_INIT), user_callback_(NULL) {}
5404 virtual ~MockAuthHandlerCanonical() {}
5405
5406 void SetResolveExpectation(Resolve resolve) {
5407 EXPECT_EQ(RESOLVE_INIT, resolve_);
5408 resolve_ = resolve;
5409 }
5410
5411 void ResetResolveExpectation() {
5412 EXPECT_EQ(RESOLVE_TESTED, resolve_);
5413 resolve_ = RESOLVE_INIT;
5414 }
5415
5416 virtual bool NeedsCanonicalName() {
5417 switch (resolve_) {
5418 case RESOLVE_SYNC:
5419 case RESOLVE_ASYNC:
5420 return true;
5421 case RESOLVE_SKIP:
5422 resolve_ = RESOLVE_TESTED;
5423 return false;
5424 default:
5425 NOTREACHED();
5426 return false;
5427 }
5428 }
5429
5430 virtual int ResolveCanonicalName(HostResolver* host_resolver,
5431 CompletionCallback* callback,
5432 const BoundNetLog& net_log) {
5433 EXPECT_NE(RESOLVE_TESTED, resolve_);
5434 int rv = OK;
5435 switch (resolve_) {
5436 case RESOLVE_SYNC:
5437 resolve_ = RESOLVE_TESTED;
5438 break;
5439 case RESOLVE_ASYNC:
5440 EXPECT_TRUE(user_callback_ == NULL);
5441 rv = ERR_IO_PENDING;
5442 user_callback_ = callback;
5443 MessageLoop::current()->PostTask(
5444 FROM_HERE,
5445 NewRunnableMethod(
5446 this, &MockAuthHandlerCanonical::OnResolveCanonicalName));
5447 break;
5448 default:
5449 NOTREACHED();
5450 break;
5451 }
5452 return rv;
5453 }
5454
5455 void OnResolveCanonicalName() {
5456 EXPECT_EQ(RESOLVE_ASYNC, resolve_);
5457 EXPECT_TRUE(user_callback_ != NULL);
5458 resolve_ = RESOLVE_TESTED;
5459 CompletionCallback* callback = user_callback_;
5460 user_callback_ = NULL;
5461 callback->Run(OK);
5462 }
5463
5464 virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) {
5465 scheme_ = "mock";
5466 score_ = 1;
5467 properties_ = 0;
5468 return true;
5469 }
5470
5471 virtual int GenerateAuthToken(const std::wstring& username,
5472 const std::wstring& password,
5473 const HttpRequestInfo* request,
5474 const ProxyInfo* proxy,
5475 std::string* auth_token) {
5476 auth_token->assign("Mock AUTH myserver.example.com");
5477 return OK;
5478 }
5479
5480 virtual int GenerateDefaultAuthToken(const HttpRequestInfo* request,
5481 const ProxyInfo* proxy,
5482 std::string* auth_token) {
5483 auth_token->assign("Mock DEFAULT_AUTH myserver.example.com");
5484 return OK;
5485 }
5486
5487 // The Factory class simply returns the same handler each time
5488 // CreateAuthHandler is called.
5489 class Factory : public HttpAuthHandlerFactory {
5490 public:
5491 Factory() {}
5492 virtual ~Factory() {}
5493
5494 void set_mock_handler(MockAuthHandlerCanonical* mock_handler) {
5495 mock_handler_ = mock_handler;
5496 }
5497 MockAuthHandlerCanonical* mock_handler() const {
5498 return mock_handler_.get();
5499 }
5500
5501 virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
5502 HttpAuth::Target target,
5503 const GURL& origin,
[email protected]fa82f932010-05-20 11:09:245504 CreateReason reason,
5505 int nonce_count,
[email protected]e5ae96a2010-04-14 20:12:455506 scoped_refptr<HttpAuthHandler>* handler) {
5507 *handler = mock_handler_;
5508 return OK;
5509 }
5510
5511 private:
5512 scoped_refptr<MockAuthHandlerCanonical> mock_handler_;
5513 };
5514
5515 private:
5516 Resolve resolve_;
5517 CompletionCallback* user_callback_;
5518};
5519
5520// Tests that ResolveCanonicalName is handled correctly by the
5521// HttpNetworkTransaction.
5522TEST_F(HttpNetworkTransactionTest, ResolveCanonicalName) {
5523 SessionDependencies session_deps;
5524 scoped_refptr<MockAuthHandlerCanonical> auth_handler(
5525 new MockAuthHandlerCanonical());
5526 auth_handler->Init(NULL);
5527 MockAuthHandlerCanonical::Factory* auth_factory(
5528 new MockAuthHandlerCanonical::Factory());
5529 auth_factory->set_mock_handler(auth_handler);
5530 session_deps.http_auth_handler_factory.reset(auth_factory);
5531
5532 for (int i = 0; i < 2; ++i) {
5533 scoped_ptr<HttpTransaction> trans(
5534 new HttpNetworkTransaction(CreateSession(&session_deps)));
5535
5536 // Set up expectations for this pass of the test. Many of the EXPECT calls
5537 // are contained inside the MockAuthHandlerCanonical codebase in response to
5538 // the expectations.
[email protected]2227c692010-05-04 15:36:115539 MockAuthHandlerCanonical::Resolve resolve =
5540 (i == 0) ?
[email protected]e5ae96a2010-04-14 20:12:455541 MockAuthHandlerCanonical::RESOLVE_SYNC :
5542 MockAuthHandlerCanonical::RESOLVE_ASYNC;
5543 auth_handler->SetResolveExpectation(resolve);
5544 HttpRequestInfo request;
5545 request.method = "GET";
5546 request.url = GURL("http://myserver/");
5547 request.load_flags = 0;
5548
5549 MockWrite data_writes1[] = {
5550 MockWrite("GET / HTTP/1.1\r\n"
5551 "Host: myserver\r\n"
5552 "Connection: keep-alive\r\n\r\n"),
5553 };
5554
5555 MockRead data_reads1[] = {
5556 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5557 MockRead("WWW-Authenticate: Mock myserver.example.com\r\n"),
5558 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5559 MockRead("Content-Length: 14\r\n\r\n"),
5560 MockRead("Unauthorized\r\n"),
5561 };
5562
5563 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5564 data_writes1, arraysize(data_writes1));
5565 session_deps.socket_factory.AddSocketDataProvider(&data1);
5566
5567 TestCompletionCallback callback1;
5568
[email protected]5a1d7ca2010-04-28 20:12:275569 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]e5ae96a2010-04-14 20:12:455570 EXPECT_EQ(ERR_IO_PENDING, rv);
5571
5572 rv = callback1.WaitForResult();
5573 EXPECT_EQ(OK, rv);
5574
5575 const HttpResponseInfo* response = trans->GetResponseInfo();
5576 EXPECT_FALSE(response == NULL);
5577
5578 // The password prompt is set after the canonical name is resolved.
5579 // If it isn't present or is incorrect, it indicates that the scheme
5580 // did not complete correctly.
5581 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5582
5583 EXPECT_EQ(L"myserver:80", response->auth_challenge->host_and_port);
5584 EXPECT_EQ(L"", response->auth_challenge->realm);
5585 EXPECT_EQ(L"mock", response->auth_challenge->scheme);
5586 auth_handler->ResetResolveExpectation();
5587 }
5588}
5589
[email protected]aeaca1f2010-04-20 22:05:215590class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
5591 public:
5592 TLSDecompressionFailureSocketDataProvider(bool fail_all)
5593 : fail_all_(fail_all) {
5594 }
5595
5596 virtual MockRead GetNextRead() {
5597 if (fail_all_)
5598 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
5599
5600 return MockRead(false /* async */,
5601 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
5602 }
5603
5604 virtual MockWriteResult OnWrite(const std::string& data) {
5605 return MockWriteResult(false /* async */, data.size());
5606 }
5607
5608 void Reset() {
5609 }
5610
5611 private:
5612 const bool fail_all_;
5613};
5614
5615// Test that we restart a connection when we see a decompression failure from
5616// the peer during the handshake. (In the real world we'll restart with SSLv3
5617// and we won't offer DEFLATE in that case.)
5618TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
5619 HttpRequestInfo request;
5620 request.method = "GET";
5621 request.url = GURL("https://tlsdecompressionfailure.example.com/");
5622 request.load_flags = 0;
5623
5624 SessionDependencies session_deps;
5625 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5626 false /* fail all reads */);
5627 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5628 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:115629 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:215630 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5631 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5632 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5633 session_deps.socket_factory.AddSSLSocketDataProvider(
5634 &ssl_socket_data_provider1);
5635 session_deps.socket_factory.AddSSLSocketDataProvider(
5636 &ssl_socket_data_provider2);
5637
5638 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5639 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5640 TestCompletionCallback callback;
5641
[email protected]5a1d7ca2010-04-28 20:12:275642 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:215643 EXPECT_EQ(ERR_IO_PENDING, rv);
5644 EXPECT_EQ(OK, callback.WaitForResult());
5645
5646 const HttpResponseInfo* response = trans->GetResponseInfo();
5647 ASSERT_TRUE(response != NULL);
5648 ASSERT_TRUE(response->headers != NULL);
5649 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5650
5651 std::string response_data;
5652 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5653 EXPECT_EQ("ok.", response_data);
5654}
5655
5656// Test that we restart a connection if we get a decompression failure from the
5657// peer while reading the first bytes from the connection. This occurs when the
5658// peer cannot handle DEFLATE but we're using False Start, so we don't notice
5659// in the handshake.
5660TEST_F(HttpNetworkTransactionTest,
5661 RestartAfterTLSDecompressionFailureWithFalseStart) {
5662 HttpRequestInfo request;
5663 request.method = "GET";
5664 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
5665 request.load_flags = 0;
5666
5667 SessionDependencies session_deps;
5668 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5669 true /* fail all reads */);
5670 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5671 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
5672 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5673 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5674 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5675 session_deps.socket_factory.AddSSLSocketDataProvider(
5676 &ssl_socket_data_provider1);
5677 session_deps.socket_factory.AddSSLSocketDataProvider(
5678 &ssl_socket_data_provider2);
5679
5680 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5681 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5682 TestCompletionCallback callback;
5683
[email protected]5a1d7ca2010-04-28 20:12:275684 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:215685 EXPECT_EQ(ERR_IO_PENDING, rv);
5686 EXPECT_EQ(OK, callback.WaitForResult());
5687
5688 const HttpResponseInfo* response = trans->GetResponseInfo();
5689 ASSERT_TRUE(response != NULL);
5690 ASSERT_TRUE(response->headers != NULL);
5691 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5692
5693 std::string response_data;
5694 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5695 EXPECT_EQ("ok.", response_data);
5696}
5697
[email protected]65041fa2010-05-21 06:56:535698// This tests the case that a request is issued via http instead of spdy after
5699// npn is negotiated.
5700TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
5701 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5702 HttpNetworkTransaction::SetNextProtos("\x08http/1.1\x07http1.1");
5703 SessionDependencies session_deps;
5704 HttpRequestInfo request;
5705 request.method = "GET";
5706 request.url = GURL("https://www.google.com/");
5707 request.load_flags = 0;
5708
5709 MockWrite data_writes[] = {
5710 MockWrite("GET / HTTP/1.1\r\n"
5711 "Host: www.google.com\r\n"
5712 "Connection: keep-alive\r\n\r\n"),
5713 };
5714
5715 MockRead data_reads[] = {
5716 MockRead("HTTP/1.1 200 OK\r\n"),
5717 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5718 MockRead("hello world"),
5719 MockRead(false, OK),
5720 };
5721
5722 SSLSocketDataProvider ssl(true, OK);
5723 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5724 ssl.next_proto = "http/1.1";
5725
5726 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5727
5728 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5729 data_writes, arraysize(data_writes));
5730 session_deps.socket_factory.AddSocketDataProvider(&data);
5731
5732 TestCompletionCallback callback;
5733
5734 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5735 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5736
5737 int rv = trans->Start(&request, &callback, BoundNetLog());
5738
5739 EXPECT_EQ(ERR_IO_PENDING, rv);
5740 EXPECT_EQ(OK, callback.WaitForResult());
5741
5742 const HttpResponseInfo* response = trans->GetResponseInfo();
5743 ASSERT_TRUE(response != NULL);
5744 ASSERT_TRUE(response->headers != NULL);
5745 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5746
5747 std::string response_data;
5748 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5749 EXPECT_EQ("hello world", response_data);
5750
5751 EXPECT_FALSE(response->was_fetched_via_spdy);
5752 EXPECT_TRUE(response->was_npn_negotiated);
5753
5754 HttpNetworkTransaction::SetNextProtos("");
5755 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5756}
[email protected]89ceba9a2009-03-21 03:46:065757} // namespace net