blob: c21634ff239fb88c95a790e1c9e68a94ccfe78ee [file] [log] [blame]
[email protected]95d88ffe2010-02-04 21:25:331// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]95d88ffe2010-02-04 21:25:338#include <vector>
[email protected]77848d12008-11-14 00:00:229
[email protected]2d731a32010-04-29 01:04:0610#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3011#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:3312#include "base/file_path.h"
13#include "base/file_util.h"
[email protected]6624b4622010-03-29 19:58:3614#include "base/scoped_ptr.h"
[email protected]169d0012010-05-10 23:20:1215#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3316#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3217#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1218#include "net/base/net_log.h"
19#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3120#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4221#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3322#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5223#include "net/base/test_completion_callback.h"
24#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1225#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0026#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2927#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5728#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5229#include "net/http/http_network_session.h"
[email protected]0877e3d2009-10-17 22:29:5730#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5231#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5332#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1133#include "net/proxy/proxy_resolver.h"
34#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4435#include "net/socket/client_socket_factory.h"
36#include "net/socket/socket_test_util.h"
37#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5438#include "net/spdy/spdy_framer.h"
39#include "net/spdy/spdy_session.h"
40#include "net/spdy/spdy_session_pool.h"
41#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5242#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1543#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5244
45//-----------------------------------------------------------------------------
46
[email protected]89ceba9a2009-03-21 03:46:0647namespace net {
48
[email protected]2d731a32010-04-29 01:04:0649class HttpNetworkSessionPeer {
50 public:
51 explicit HttpNetworkSessionPeer(
52 const scoped_refptr<HttpNetworkSession>& session)
53 : session_(session) {}
54
55 void SetTCPSocketPool(const scoped_refptr<TCPClientSocketPool>& pool) {
56 session_->tcp_socket_pool_ = pool;
57 }
58
59 void SetSocketPoolForSOCKSProxy(
60 const HostPortPair& socks_proxy,
61 const scoped_refptr<SOCKSClientSocketPool>& pool) {
[email protected]e60e47a2010-07-14 03:37:1862 session_->socks_socket_pools_[socks_proxy] = pool;
[email protected]2d731a32010-04-29 01:04:0663 }
64
65 void SetSocketPoolForHTTPProxy(
66 const HostPortPair& http_proxy,
[email protected]e772db3f2010-07-12 18:11:1367 const scoped_refptr<HttpProxyClientSocketPool>& pool) {
[email protected]e60e47a2010-07-14 03:37:1868 session_->http_proxy_socket_pools_[http_proxy] = pool;
69 }
70
71 void SetSSLSocketPool(const scoped_refptr<SSLClientSocketPool>& pool) {
72 session_->ssl_socket_pool_ = pool;
73 }
74
75 void SetSocketPoolForSSLWithProxy(
76 const HostPortPair& proxy_host,
77 const scoped_refptr<SSLClientSocketPool>& pool) {
78 session_->ssl_socket_pools_for_proxies_[proxy_host] = pool;
[email protected]2d731a32010-04-29 01:04:0679 }
80
81 private:
82 const scoped_refptr<HttpNetworkSession> session_;
83
84 DISALLOW_COPY_AND_ASSIGN(HttpNetworkSessionPeer);
85};
86
[email protected]e44de5d2009-06-05 20:12:4587// Helper to manage the lifetimes of the dependencies for a
88// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4489struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5990 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4291 SessionDependencies()
92 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:3793 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:1094 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:5295 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]a7ea8832010-07-12 17:54:5496 spdy_session_pool(new SpdySessionPool()),
97 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5998
99 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:45100 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:42101 : host_resolver(new MockHostResolver),
102 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:10103 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:52104 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]a7ea8832010-07-12 17:54:54105 spdy_session_pool(new SpdySessionPool()),
106 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59107
[email protected]a2c2fb92009-07-18 07:31:04108 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:09109 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:42110 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:59111 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50112 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a554a8262010-05-20 00:13:52113 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]a7ea8832010-07-12 17:54:54114 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59115};
116
[email protected]1c773ea12009-04-28 19:58:42117ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50118 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48119 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39120 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53121}
122
[email protected]228ff742009-06-05 01:19:59123HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]66761b952010-06-25 21:30:38124 return new HttpNetworkSession(session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:09125 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42126 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10127 session_deps->ssl_config_service,
[email protected]a554a8262010-05-20 00:13:52128 session_deps->spdy_session_pool,
[email protected]06650c52010-06-03 00:49:17129 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44130 NULL,
[email protected]a7ea8832010-07-12 17:54:54131 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14132}
133
[email protected]89836e22008-09-25 20:33:42134class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52135 public:
[email protected]2ff8b312010-04-26 22:20:54136 virtual void SetUp() {
137 spdy::SpdyFramer::set_enable_compression_default(false);
138 }
139
[email protected]0e75a732008-10-16 20:36:09140 virtual void TearDown() {
[email protected]2ff8b312010-04-26 22:20:54141 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09142 // Empty the current queue.
143 MessageLoop::current()->RunAllPending();
144 PlatformTest::TearDown();
145 }
146
[email protected]3d2a59b2008-09-26 19:44:25147 protected:
148 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52149
[email protected]ff007e162009-05-23 09:13:15150 struct SimpleGetHelperResult {
151 int rv;
152 std::string status_line;
153 std::string response_data;
154 };
initial.commit586acc5fe2008-07-26 22:42:52155
[email protected]31a2bfe2010-02-09 08:03:39156 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
157 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15158 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52159
[email protected]228ff742009-06-05 01:19:59160 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40161 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43162 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52163
[email protected]ff007e162009-05-23 09:13:15164 HttpRequestInfo request;
165 request.method = "GET";
166 request.url = GURL("http://www.google.com/");
167 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52168
[email protected]31a2bfe2010-02-09 08:03:39169 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59170 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52171
[email protected]ff007e162009-05-23 09:13:15172 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52173
[email protected]169d0012010-05-10 23:20:12174 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
175 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15176 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52177
[email protected]ff007e162009-05-23 09:13:15178 out.rv = callback.WaitForResult();
179 if (out.rv != OK)
180 return out;
181
182 const HttpResponseInfo* response = trans->GetResponseInfo();
183 EXPECT_TRUE(response != NULL);
184
185 EXPECT_TRUE(response->headers != NULL);
186 out.status_line = response->headers->GetStatusLine();
187
188 rv = ReadTransaction(trans.get(), &out.response_data);
189 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39190 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12191 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
192 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39193 ExpectLogContainsSomewhere(
194 log.entries(), pos,
195 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
196 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15197
[email protected]aecfbf22008-10-16 02:02:47198 return out;
[email protected]ff007e162009-05-23 09:13:15199 }
initial.commit586acc5fe2008-07-26 22:42:52200
[email protected]ff007e162009-05-23 09:13:15201 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
202 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52203
[email protected]ff007e162009-05-23 09:13:15204 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15205};
[email protected]231d5a32008-09-13 00:45:27206
[email protected]15a5ccf82008-10-23 19:57:43207// Fill |str| with a long header list that consumes >= |size| bytes.
208void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19209 const char* row =
210 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
211 const int sizeof_row = strlen(row);
212 const int num_rows = static_cast<int>(
213 ceil(static_cast<float>(size) / sizeof_row));
214 const int sizeof_data = num_rows * sizeof_row;
215 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43216 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51217
[email protected]4ddaf2502008-10-23 18:26:19218 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43219 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19220}
221
[email protected]385a4672009-03-11 22:21:29222// Alternative functions that eliminate randomness and dependency on the local
223// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20224void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29225 static const uint8 bytes[] = {
226 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
227 };
228 static size_t current_byte = 0;
229 for (size_t i = 0; i < n; ++i) {
230 output[i] = bytes[current_byte++];
231 current_byte %= arraysize(bytes);
232 }
233}
234
[email protected]fe2bc6a2009-03-23 16:52:20235void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29236 static const uint8 bytes[] = {
237 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
238 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
239 };
240 static size_t current_byte = 0;
241 for (size_t i = 0; i < n; ++i) {
242 output[i] = bytes[current_byte++];
243 current_byte %= arraysize(bytes);
244 }
245}
246
[email protected]fe2bc6a2009-03-23 16:52:20247std::string MockGetHostName() {
248 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29249}
250
[email protected]e60e47a2010-07-14 03:37:18251template<typename ParentPool>
252class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31253 public:
[email protected]e60e47a2010-07-14 03:37:18254 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
255
[email protected]d80a4322009-08-14 07:07:49256 const std::string last_group_name_received() const {
257 return last_group_name_;
258 }
259
[email protected]684970b2009-08-14 04:54:46260 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49261 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31262 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31263 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46264 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53265 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31266 last_group_name_ = group_name;
267 return ERR_IO_PENDING;
268 }
[email protected]04e5be32009-06-26 20:00:31269 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21270 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31271 virtual void ReleaseSocket(const std::string& group_name,
272 ClientSocket* socket) {}
273 virtual void CloseIdleSockets() {}
274 virtual HostResolver* GetHostResolver() const {
275 return NULL;
276 }
277 virtual int IdleSocketCount() const {
278 return 0;
279 }
280 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
281 return 0;
282 }
283 virtual LoadState GetLoadState(const std::string& group_name,
284 const ClientSocketHandle* handle) const {
285 return LOAD_STATE_IDLE;
286 }
[email protected]a796bcec2010-03-22 17:17:26287 virtual base::TimeDelta ConnectionTimeout() const {
288 return base::TimeDelta();
289 }
[email protected]d80a4322009-08-14 07:07:49290
291 private:
[email protected]04e5be32009-06-26 20:00:31292 std::string last_group_name_;
293};
294
[email protected]2d731a32010-04-29 01:04:06295typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11296CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13297typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
298CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06299typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11300CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18301typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
302CaptureGroupNameSSLSocketPool;
303
304template<typename ParentPool>
305CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
306 HttpNetworkSession* session)
307 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
308
309template<>
310CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
311 HttpNetworkSession* session)
312 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
313 NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11314
[email protected]231d5a32008-09-13 00:45:27315//-----------------------------------------------------------------------------
316
317TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59318 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40319 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43320 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27321}
322
323TEST_F(HttpNetworkTransactionTest, SimpleGET) {
324 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35325 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
326 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42327 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27328 };
[email protected]31a2bfe2010-02-09 08:03:39329 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
330 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42331 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27332 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
333 EXPECT_EQ("hello world", out.response_data);
334}
335
336// Response with no status line.
337TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
338 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35339 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42340 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27341 };
[email protected]31a2bfe2010-02-09 08:03:39342 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
343 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42344 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27345 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
346 EXPECT_EQ("hello world", out.response_data);
347}
348
349// Allow up to 4 bytes of junk to precede status line.
350TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
351 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35352 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42353 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27354 };
[email protected]31a2bfe2010-02-09 08:03:39355 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
356 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42357 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27358 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
359 EXPECT_EQ("DATA", out.response_data);
360}
361
362// Allow up to 4 bytes of junk to precede status line.
363TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
364 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35365 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42366 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27367 };
[email protected]31a2bfe2010-02-09 08:03:39368 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
369 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42370 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27371 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
372 EXPECT_EQ("DATA", out.response_data);
373}
374
375// Beyond 4 bytes of slop and it should fail to find a status line.
376TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
377 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35378 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42379 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27380 };
[email protected]31a2bfe2010-02-09 08:03:39381 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
382 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42383 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25384 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
385 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27386}
387
388// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
389TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
390 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35391 MockRead("\n"),
392 MockRead("\n"),
393 MockRead("Q"),
394 MockRead("J"),
395 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42396 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27397 };
[email protected]31a2bfe2010-02-09 08:03:39398 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
399 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42400 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27401 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
402 EXPECT_EQ("DATA", out.response_data);
403}
404
405// Close the connection before enough bytes to have a status line.
406TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
407 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35408 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42409 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27410 };
[email protected]31a2bfe2010-02-09 08:03:39411 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
412 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42413 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27414 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
415 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52416}
417
[email protected]f9d44aa2008-09-23 23:57:17418// Simulate a 204 response, lacking a Content-Length header, sent over a
419// persistent connection. The response should still terminate since a 204
420// cannot have a response body.
421TEST_F(HttpNetworkTransactionTest, StopsReading204) {
422 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35423 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
424 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42425 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17426 };
[email protected]31a2bfe2010-02-09 08:03:39427 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
428 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42429 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17430 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
431 EXPECT_EQ("", out.response_data);
432}
433
[email protected]0877e3d2009-10-17 22:29:57434// A simple request using chunked encoding with some extra data after.
435// (Like might be seen in a pipelined response.)
436TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
437 MockRead data_reads[] = {
438 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
439 MockRead("5\r\nHello\r\n"),
440 MockRead("1\r\n"),
441 MockRead(" \r\n"),
442 MockRead("5\r\nworld\r\n"),
443 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
444 MockRead(false, OK),
445 };
[email protected]31a2bfe2010-02-09 08:03:39446 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
447 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57448 EXPECT_EQ(OK, out.rv);
449 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
450 EXPECT_EQ("Hello world", out.response_data);
451}
452
[email protected]ef0faf2e72009-03-05 23:27:23453// Do a request using the HEAD method. Verify that we don't try to read the
454// message body (since HEAD has none).
455TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59456 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40457 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43458 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23459
[email protected]1c773ea12009-04-28 19:58:42460 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23461 request.method = "HEAD";
462 request.url = GURL("http://www.google.com/");
463 request.load_flags = 0;
464
465 MockWrite data_writes1[] = {
466 MockWrite("HEAD / HTTP/1.1\r\n"
467 "Host: www.google.com\r\n"
468 "Connection: keep-alive\r\n"
469 "Content-Length: 0\r\n\r\n"),
470 };
471 MockRead data_reads1[] = {
472 MockRead("HTTP/1.1 404 Not Found\r\n"),
473 MockRead("Server: Blah\r\n"),
474 MockRead("Content-Length: 1234\r\n\r\n"),
475
476 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42477 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23478 };
479
[email protected]31a2bfe2010-02-09 08:03:39480 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
481 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59482 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23483
484 TestCompletionCallback callback1;
485
[email protected]5a1d7ca2010-04-28 20:12:27486 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42487 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23488
489 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42490 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23491
[email protected]1c773ea12009-04-28 19:58:42492 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23493 EXPECT_FALSE(response == NULL);
494
495 // Check that the headers got parsed.
496 EXPECT_TRUE(response->headers != NULL);
497 EXPECT_EQ(1234, response->headers->GetContentLength());
498 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
499
500 std::string server_header;
501 void* iter = NULL;
502 bool has_server_header = response->headers->EnumerateHeader(
503 &iter, "Server", &server_header);
504 EXPECT_TRUE(has_server_header);
505 EXPECT_EQ("Blah", server_header);
506
507 // Reading should give EOF right away, since there is no message body
508 // (despite non-zero content-length).
509 std::string response_data;
510 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42511 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23512 EXPECT_EQ("", response_data);
513}
514
initial.commit586acc5fe2008-07-26 22:42:52515TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59516 SessionDependencies session_deps;
517 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52518
519 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35520 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
521 MockRead("hello"),
522 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
523 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42524 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52525 };
[email protected]31a2bfe2010-02-09 08:03:39526 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59527 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52528
529 const char* kExpectedResponseData[] = {
530 "hello", "world"
531 };
532
533 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43534 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52535
[email protected]1c773ea12009-04-28 19:58:42536 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52537 request.method = "GET";
538 request.url = GURL("http://www.google.com/");
539 request.load_flags = 0;
540
541 TestCompletionCallback callback;
542
[email protected]5a1d7ca2010-04-28 20:12:27543 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42544 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52545
546 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42547 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52548
[email protected]1c773ea12009-04-28 19:58:42549 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52550 EXPECT_TRUE(response != NULL);
551
552 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25553 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52554
555 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57556 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42557 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25558 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52559 }
560}
561
562TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59563 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40564 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43565 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52566
[email protected]1c773ea12009-04-28 19:58:42567 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52568 request.method = "POST";
569 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42570 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52571 request.upload_data->AppendBytes("foo", 3);
572 request.load_flags = 0;
573
574 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35575 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
576 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
577 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42578 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52579 };
[email protected]31a2bfe2010-02-09 08:03:39580 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59581 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52582
583 TestCompletionCallback callback;
584
[email protected]5a1d7ca2010-04-28 20:12:27585 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42586 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52587
588 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42589 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52590
[email protected]1c773ea12009-04-28 19:58:42591 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52592 EXPECT_TRUE(response != NULL);
593
594 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25595 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52596
597 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57598 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42599 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25600 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52601}
602
[email protected]3a2d3662009-03-27 03:49:14603// This test is almost the same as Ignores100 above, but the response contains
604// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57605// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14606TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59607 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40608 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43609 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14610
[email protected]1c773ea12009-04-28 19:58:42611 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14612 request.method = "GET";
613 request.url = GURL("http://www.foo.com/");
614 request.load_flags = 0;
615
616 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57617 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
618 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14619 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42620 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14621 };
[email protected]31a2bfe2010-02-09 08:03:39622 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59623 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14624
625 TestCompletionCallback callback;
626
[email protected]5a1d7ca2010-04-28 20:12:27627 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42628 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14629
630 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42631 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14632
[email protected]1c773ea12009-04-28 19:58:42633 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14634 EXPECT_TRUE(response != NULL);
635
636 EXPECT_TRUE(response->headers != NULL);
637 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
638
639 std::string response_data;
640 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42641 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14642 EXPECT_EQ("hello world", response_data);
643}
644
[email protected]ee9410e72010-01-07 01:42:38645TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
646 SessionDependencies session_deps;
647 scoped_ptr<HttpTransaction> trans(
648 new HttpNetworkTransaction(CreateSession(&session_deps)));
649
650 HttpRequestInfo request;
651 request.method = "POST";
652 request.url = GURL("http://www.foo.com/");
653 request.load_flags = 0;
654
655 MockRead data_reads[] = {
656 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
657 MockRead(true, 0),
658 };
[email protected]31a2bfe2010-02-09 08:03:39659 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38660 session_deps.socket_factory.AddSocketDataProvider(&data);
661
662 TestCompletionCallback callback;
663
[email protected]5a1d7ca2010-04-28 20:12:27664 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38665 EXPECT_EQ(ERR_IO_PENDING, rv);
666
667 rv = callback.WaitForResult();
668 EXPECT_EQ(OK, rv);
669
670 std::string response_data;
671 rv = ReadTransaction(trans.get(), &response_data);
672 EXPECT_EQ(OK, rv);
673 EXPECT_EQ("", response_data);
674}
675
676TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
677 SessionDependencies session_deps;
678 scoped_ptr<HttpTransaction> trans(
679 new HttpNetworkTransaction(CreateSession(&session_deps)));
680
681 HttpRequestInfo request;
682 request.method = "POST";
683 request.url = GURL("http://www.foo.com/");
684 request.load_flags = 0;
685
686 MockRead data_reads[] = {
687 MockRead(true, 0),
688 };
[email protected]31a2bfe2010-02-09 08:03:39689 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38690 session_deps.socket_factory.AddSocketDataProvider(&data);
691
692 TestCompletionCallback callback;
693
[email protected]5a1d7ca2010-04-28 20:12:27694 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38695 EXPECT_EQ(ERR_IO_PENDING, rv);
696
697 rv = callback.WaitForResult();
698 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
699}
700
[email protected]3d2a59b2008-09-26 19:44:25701// read_failure specifies a read failure that should cause the network
702// transaction to resend the request.
703void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
704 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59705 SessionDependencies session_deps;
706 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52707
[email protected]1c773ea12009-04-28 19:58:42708 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52709 request.method = "GET";
710 request.url = GURL("http://www.foo.com/");
711 request.load_flags = 0;
712
713 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35714 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
715 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25716 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52717 };
[email protected]31a2bfe2010-02-09 08:03:39718 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59719 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52720
721 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35722 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
723 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42724 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52725 };
[email protected]31a2bfe2010-02-09 08:03:39726 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59727 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52728
729 const char* kExpectedResponseData[] = {
730 "hello", "world"
731 };
732
733 for (int i = 0; i < 2; ++i) {
734 TestCompletionCallback callback;
735
[email protected]5695b8c2009-09-30 21:36:43736 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52737
[email protected]5a1d7ca2010-04-28 20:12:27738 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42739 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52740
741 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42742 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52743
[email protected]1c773ea12009-04-28 19:58:42744 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52745 EXPECT_TRUE(response != NULL);
746
747 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25748 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52749
750 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57751 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42752 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25753 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52754 }
755}
[email protected]3d2a59b2008-09-26 19:44:25756
757TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42758 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25759 KeepAliveConnectionResendRequestTest(read_failure);
760}
761
762TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42763 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25764 KeepAliveConnectionResendRequestTest(read_failure);
765}
766
767TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59768 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40769 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43770 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25771
[email protected]1c773ea12009-04-28 19:58:42772 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25773 request.method = "GET";
774 request.url = GURL("http://www.google.com/");
775 request.load_flags = 0;
776
777 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42778 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35779 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
780 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42781 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25782 };
[email protected]31a2bfe2010-02-09 08:03:39783 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59784 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25785
786 TestCompletionCallback callback;
787
[email protected]5a1d7ca2010-04-28 20:12:27788 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42789 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25790
791 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42792 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25793
[email protected]1c773ea12009-04-28 19:58:42794 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25795 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25796}
797
798// What do various browsers do when the server closes a non-keepalive
799// connection without sending any response header or body?
800//
801// IE7: error page
802// Safari 3.1.2 (Windows): error page
803// Firefox 3.0.1: blank page
804// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42805// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
806// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25807TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
808 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42809 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35810 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
811 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42812 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25813 };
[email protected]31a2bfe2010-02-09 08:03:39814 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
815 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42816 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25817}
[email protected]038e9a32008-10-08 22:40:16818
[email protected]fc31d6a42010-06-24 18:05:13819// Test that we correctly reuse a keep-alive connection after receiving a 304.
820TEST_F(HttpNetworkTransactionTest, KeepAliveAfter304) {
821 SessionDependencies session_deps;
822 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
823
824 HttpRequestInfo request;
825 request.method = "GET";
826 request.url = GURL("http://www.foo.com/");
827 request.load_flags = 0;
828
829 MockRead data1_reads[] = {
830 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
831 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
832 MockRead("hello"),
833 };
834 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
835 session_deps.socket_factory.AddSocketDataProvider(&data1);
836
837 MockRead data2_reads[] = {
838 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
839 };
840 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
841 session_deps.socket_factory.AddSocketDataProvider(&data2);
842
843 for (int i = 0; i < 2; ++i) {
844 TestCompletionCallback callback;
845
846 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
847
848 int rv = trans->Start(&request, &callback, BoundNetLog());
849 EXPECT_EQ(ERR_IO_PENDING, rv);
850
851 rv = callback.WaitForResult();
852 EXPECT_EQ(OK, rv);
853
854 const HttpResponseInfo* response = trans->GetResponseInfo();
855 EXPECT_TRUE(response != NULL);
856
857 EXPECT_TRUE(response->headers != NULL);
858 if (i == 0) {
859 EXPECT_EQ("HTTP/1.1 304 Not Modified",
860 response->headers->GetStatusLine());
861 // We intentionally don't read the response in this case, to reflect how
862 // HttpCache::Transaction uses HttpNetworkTransaction.
863 } else {
864 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
865 std::string response_data;
866 rv = ReadTransaction(trans.get(), &response_data);
867 EXPECT_EQ(OK, rv);
868 EXPECT_EQ("hello", response_data);
869 }
870 }
871}
872
[email protected]038e9a32008-10-08 22:40:16873// Test the request-challenge-retry sequence for basic auth.
874// (basic auth is the easiest to mock, because it has no randomness).
875TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59876 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40877 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43878 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16879
[email protected]1c773ea12009-04-28 19:58:42880 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16881 request.method = "GET";
882 request.url = GURL("http://www.google.com/");
883 request.load_flags = 0;
884
[email protected]f9ee6b52008-11-08 06:46:23885 MockWrite data_writes1[] = {
886 MockWrite("GET / HTTP/1.1\r\n"
887 "Host: www.google.com\r\n"
888 "Connection: keep-alive\r\n\r\n"),
889 };
890
[email protected]038e9a32008-10-08 22:40:16891 MockRead data_reads1[] = {
892 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
893 // Give a couple authenticate options (only the middle one is actually
894 // supported).
[email protected]22927ad2009-09-21 19:56:19895 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16896 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
897 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
898 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
899 // Large content-length -- won't matter, as connection will be reset.
900 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42901 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16902 };
903
904 // After calling trans->RestartWithAuth(), this is the request we should
905 // be issuing -- the final header line contains the credentials.
906 MockWrite data_writes2[] = {
907 MockWrite("GET / HTTP/1.1\r\n"
908 "Host: www.google.com\r\n"
909 "Connection: keep-alive\r\n"
910 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
911 };
912
913 // Lastly, the server responds with the actual content.
914 MockRead data_reads2[] = {
915 MockRead("HTTP/1.0 200 OK\r\n"),
916 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
917 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42918 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16919 };
920
[email protected]31a2bfe2010-02-09 08:03:39921 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
922 data_writes1, arraysize(data_writes1));
923 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
924 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59925 session_deps.socket_factory.AddSocketDataProvider(&data1);
926 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16927
928 TestCompletionCallback callback1;
929
[email protected]5a1d7ca2010-04-28 20:12:27930 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42931 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16932
933 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42934 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16935
[email protected]1c773ea12009-04-28 19:58:42936 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16937 EXPECT_FALSE(response == NULL);
938
939 // The password prompt info should have been set in response->auth_challenge.
940 EXPECT_FALSE(response->auth_challenge.get() == NULL);
941
[email protected]71e4573a2009-05-21 22:03:00942 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16943 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
944 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
945
946 TestCompletionCallback callback2;
947
948 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42949 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16950
951 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42952 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16953
954 response = trans->GetResponseInfo();
955 EXPECT_FALSE(response == NULL);
956 EXPECT_TRUE(response->auth_challenge.get() == NULL);
957 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16958}
959
[email protected]861fcd52009-08-26 02:33:46960TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
961 SessionDependencies session_deps;
962 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43963 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46964
965 HttpRequestInfo request;
966 request.method = "GET";
967 request.url = GURL("http://www.google.com/");
968 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
969
970 MockWrite data_writes[] = {
971 MockWrite("GET / HTTP/1.1\r\n"
972 "Host: www.google.com\r\n"
973 "Connection: keep-alive\r\n\r\n"),
974 };
975
976 MockRead data_reads[] = {
977 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
978 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
979 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
980 // Large content-length -- won't matter, as connection will be reset.
981 MockRead("Content-Length: 10000\r\n\r\n"),
982 MockRead(false, ERR_FAILED),
983 };
984
[email protected]31a2bfe2010-02-09 08:03:39985 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
986 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59987 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46988 TestCompletionCallback callback;
989
[email protected]5a1d7ca2010-04-28 20:12:27990 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:46991 EXPECT_EQ(ERR_IO_PENDING, rv);
992
993 rv = callback.WaitForResult();
994 EXPECT_EQ(0, rv);
995
996 const HttpResponseInfo* response = trans->GetResponseInfo();
997 ASSERT_FALSE(response == NULL);
998 EXPECT_TRUE(response->auth_challenge.get() == NULL);
999}
1000
[email protected]2d2697f92009-02-18 21:00:321001// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1002// connection.
1003TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:591004 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401005 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431006 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321007
[email protected]1c773ea12009-04-28 19:58:421008 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321009 request.method = "GET";
1010 request.url = GURL("http://www.google.com/");
1011 request.load_flags = 0;
1012
1013 MockWrite data_writes1[] = {
1014 MockWrite("GET / HTTP/1.1\r\n"
1015 "Host: www.google.com\r\n"
1016 "Connection: keep-alive\r\n\r\n"),
1017
1018 // After calling trans->RestartWithAuth(), this is the request we should
1019 // be issuing -- the final header line contains the credentials.
1020 MockWrite("GET / HTTP/1.1\r\n"
1021 "Host: www.google.com\r\n"
1022 "Connection: keep-alive\r\n"
1023 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1024 };
1025
1026 MockRead data_reads1[] = {
1027 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1028 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1029 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1030 MockRead("Content-Length: 14\r\n\r\n"),
1031 MockRead("Unauthorized\r\n"),
1032
1033 // Lastly, the server responds with the actual content.
1034 MockRead("HTTP/1.1 200 OK\r\n"),
1035 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1036 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421037 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321038 };
1039
[email protected]31a2bfe2010-02-09 08:03:391040 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1041 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591042 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321043
1044 TestCompletionCallback callback1;
1045
[email protected]5a1d7ca2010-04-28 20:12:271046 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421047 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321048
1049 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421050 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321051
[email protected]1c773ea12009-04-28 19:58:421052 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321053 EXPECT_FALSE(response == NULL);
1054
1055 // The password prompt info should have been set in response->auth_challenge.
1056 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1057
[email protected]71e4573a2009-05-21 22:03:001058 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321059 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1060 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1061
1062 TestCompletionCallback callback2;
1063
1064 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421065 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321066
1067 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421068 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321069
1070 response = trans->GetResponseInfo();
1071 EXPECT_FALSE(response == NULL);
1072 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1073 EXPECT_EQ(100, response->headers->GetContentLength());
1074}
1075
1076// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1077// connection and with no response body to drain.
1078TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591079 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401080 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431081 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321082
[email protected]1c773ea12009-04-28 19:58:421083 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321084 request.method = "GET";
1085 request.url = GURL("http://www.google.com/");
1086 request.load_flags = 0;
1087
1088 MockWrite data_writes1[] = {
1089 MockWrite("GET / HTTP/1.1\r\n"
1090 "Host: www.google.com\r\n"
1091 "Connection: keep-alive\r\n\r\n"),
1092
1093 // After calling trans->RestartWithAuth(), this is the request we should
1094 // be issuing -- the final header line contains the credentials.
1095 MockWrite("GET / HTTP/1.1\r\n"
1096 "Host: www.google.com\r\n"
1097 "Connection: keep-alive\r\n"
1098 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1099 };
1100
[email protected]2d2697f92009-02-18 21:00:321101 MockRead data_reads1[] = {
1102 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1103 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311104 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321105
1106 // Lastly, the server responds with the actual content.
1107 MockRead("HTTP/1.1 200 OK\r\n"),
1108 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1109 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421110 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321111 };
1112
[email protected]31a2bfe2010-02-09 08:03:391113 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1114 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591115 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321116
1117 TestCompletionCallback callback1;
1118
[email protected]5a1d7ca2010-04-28 20:12:271119 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421120 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321121
1122 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421123 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321124
[email protected]1c773ea12009-04-28 19:58:421125 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321126 EXPECT_FALSE(response == NULL);
1127
1128 // The password prompt info should have been set in response->auth_challenge.
1129 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1130
[email protected]71e4573a2009-05-21 22:03:001131 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321132 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1133 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1134
1135 TestCompletionCallback callback2;
1136
1137 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421138 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321139
1140 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421141 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321142
1143 response = trans->GetResponseInfo();
1144 EXPECT_FALSE(response == NULL);
1145 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1146 EXPECT_EQ(100, response->headers->GetContentLength());
1147}
1148
1149// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1150// connection and with a large response body to drain.
1151TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591152 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401153 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431154 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321155
[email protected]1c773ea12009-04-28 19:58:421156 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321157 request.method = "GET";
1158 request.url = GURL("http://www.google.com/");
1159 request.load_flags = 0;
1160
1161 MockWrite data_writes1[] = {
1162 MockWrite("GET / HTTP/1.1\r\n"
1163 "Host: www.google.com\r\n"
1164 "Connection: keep-alive\r\n\r\n"),
1165
1166 // After calling trans->RestartWithAuth(), this is the request we should
1167 // be issuing -- the final header line contains the credentials.
1168 MockWrite("GET / HTTP/1.1\r\n"
1169 "Host: www.google.com\r\n"
1170 "Connection: keep-alive\r\n"
1171 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1172 };
1173
1174 // Respond with 5 kb of response body.
1175 std::string large_body_string("Unauthorized");
1176 large_body_string.append(5 * 1024, ' ');
1177 large_body_string.append("\r\n");
1178
1179 MockRead data_reads1[] = {
1180 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1181 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1182 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1183 // 5134 = 12 + 5 * 1024 + 2
1184 MockRead("Content-Length: 5134\r\n\r\n"),
1185 MockRead(true, large_body_string.data(), large_body_string.size()),
1186
1187 // Lastly, the server responds with the actual content.
1188 MockRead("HTTP/1.1 200 OK\r\n"),
1189 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1190 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421191 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321192 };
1193
[email protected]31a2bfe2010-02-09 08:03:391194 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1195 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591196 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321197
1198 TestCompletionCallback callback1;
1199
[email protected]5a1d7ca2010-04-28 20:12:271200 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421201 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321202
1203 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421204 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321205
[email protected]1c773ea12009-04-28 19:58:421206 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321207 EXPECT_FALSE(response == NULL);
1208
1209 // The password prompt info should have been set in response->auth_challenge.
1210 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1211
[email protected]71e4573a2009-05-21 22:03:001212 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321213 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1214 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1215
1216 TestCompletionCallback callback2;
1217
1218 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421219 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321220
1221 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421222 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321223
1224 response = trans->GetResponseInfo();
1225 EXPECT_FALSE(response == NULL);
1226 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1227 EXPECT_EQ(100, response->headers->GetContentLength());
1228}
1229
1230// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311231// connection, but the server gets impatient and closes the connection.
1232TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1233 SessionDependencies session_deps;
1234 scoped_ptr<HttpTransaction> trans(
1235 new HttpNetworkTransaction(CreateSession(&session_deps)));
1236
1237 HttpRequestInfo request;
1238 request.method = "GET";
1239 request.url = GURL("http://www.google.com/");
1240 request.load_flags = 0;
1241
1242 MockWrite data_writes1[] = {
1243 MockWrite("GET / HTTP/1.1\r\n"
1244 "Host: www.google.com\r\n"
1245 "Connection: keep-alive\r\n\r\n"),
1246 // This simulates the seemingly successful write to a closed connection
1247 // if the bug is not fixed.
1248 MockWrite("GET / HTTP/1.1\r\n"
1249 "Host: www.google.com\r\n"
1250 "Connection: keep-alive\r\n"
1251 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1252 };
1253
1254 MockRead data_reads1[] = {
1255 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1256 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1257 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1258 MockRead("Content-Length: 14\r\n\r\n"),
1259 // Tell MockTCPClientSocket to simulate the server closing the connection.
1260 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1261 MockRead("Unauthorized\r\n"),
1262 MockRead(false, OK), // The server closes the connection.
1263 };
1264
1265 // After calling trans->RestartWithAuth(), this is the request we should
1266 // be issuing -- the final header line contains the credentials.
1267 MockWrite data_writes2[] = {
1268 MockWrite("GET / HTTP/1.1\r\n"
1269 "Host: www.google.com\r\n"
1270 "Connection: keep-alive\r\n"
1271 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1272 };
1273
1274 // Lastly, the server responds with the actual content.
1275 MockRead data_reads2[] = {
1276 MockRead("HTTP/1.1 200 OK\r\n"),
1277 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1278 MockRead("Content-Length: 100\r\n\r\n"),
1279 MockRead(false, OK),
1280 };
1281
[email protected]31a2bfe2010-02-09 08:03:391282 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1283 data_writes1, arraysize(data_writes1));
1284 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1285 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311286 session_deps.socket_factory.AddSocketDataProvider(&data1);
1287 session_deps.socket_factory.AddSocketDataProvider(&data2);
1288
1289 TestCompletionCallback callback1;
1290
[email protected]5a1d7ca2010-04-28 20:12:271291 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311292 EXPECT_EQ(ERR_IO_PENDING, rv);
1293
1294 rv = callback1.WaitForResult();
1295 EXPECT_EQ(OK, rv);
1296
1297 const HttpResponseInfo* response = trans->GetResponseInfo();
1298 EXPECT_FALSE(response == NULL);
1299
1300 // The password prompt info should have been set in response->auth_challenge.
1301 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1302
1303 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1304 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1305 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1306
1307 TestCompletionCallback callback2;
1308
1309 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1310 EXPECT_EQ(ERR_IO_PENDING, rv);
1311
1312 rv = callback2.WaitForResult();
1313 EXPECT_EQ(OK, rv);
1314
1315 response = trans->GetResponseInfo();
1316 ASSERT_FALSE(response == NULL);
1317 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1318 EXPECT_EQ(100, response->headers->GetContentLength());
1319}
1320
1321// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321322// proxy connection, when setting up an SSL tunnel.
1323TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1324 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591325 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541326 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1327 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591328 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321329
[email protected]5695b8c2009-09-30 21:36:431330 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321331
[email protected]1c773ea12009-04-28 19:58:421332 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321333 request.method = "GET";
1334 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461335 // Ensure that proxy authentication is attempted even
1336 // when the no authentication data flag is set.
1337 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321338
1339 // Since we have proxy, should try to establish tunnel.
1340 MockWrite data_writes1[] = {
1341 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451342 "Host: www.google.com\r\n"
1343 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321344
1345 // After calling trans->RestartWithAuth(), this is the request we should
1346 // be issuing -- the final header line contains the credentials.
1347 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1348 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451349 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321350 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1351 };
1352
1353 // The proxy responds to the connect with a 407, using a persistent
1354 // connection.
1355 MockRead data_reads1[] = {
1356 // No credentials.
1357 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1358 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1359 MockRead("Content-Length: 10\r\n\r\n"),
1360 MockRead("0123456789"),
1361
1362 // Wrong credentials (wrong password).
1363 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1364 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1365 MockRead("Content-Length: 10\r\n\r\n"),
1366 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421367 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321368 };
1369
[email protected]31a2bfe2010-02-09 08:03:391370 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1371 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591372 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321373
1374 TestCompletionCallback callback1;
1375
[email protected]dbb83db2010-05-11 18:13:391376 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421377 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321378
1379 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421380 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391381 size_t pos = ExpectLogContainsSomewhere(
1382 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1383 NetLog::PHASE_NONE);
1384 ExpectLogContainsSomewhere(
1385 log.entries(), pos,
1386 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1387 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321388
[email protected]1c773ea12009-04-28 19:58:421389 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321390 EXPECT_FALSE(response == NULL);
1391
1392 EXPECT_TRUE(response->headers->IsKeepAlive());
1393 EXPECT_EQ(407, response->headers->response_code());
1394 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421395 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321396
1397 // The password prompt info should have been set in response->auth_challenge.
1398 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1399
[email protected]71e4573a2009-05-21 22:03:001400 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321401 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1402 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1403
1404 TestCompletionCallback callback2;
1405
1406 // Wrong password (should be "bar").
1407 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421408 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321409
1410 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421411 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321412
1413 response = trans->GetResponseInfo();
1414 EXPECT_FALSE(response == NULL);
1415
1416 EXPECT_TRUE(response->headers->IsKeepAlive());
1417 EXPECT_EQ(407, response->headers->response_code());
1418 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421419 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321420
1421 // The password prompt info should have been set in response->auth_challenge.
1422 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1423
[email protected]71e4573a2009-05-21 22:03:001424 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321425 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1426 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131427
[email protected]e60e47a2010-07-14 03:37:181428 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1429 // out of scope.
1430 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321431}
1432
[email protected]a8e9b162009-03-12 00:06:441433// Test that we don't read the response body when we fail to establish a tunnel,
1434// even if the user cancels the proxy's auth attempt.
1435TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1436 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591437 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441438
[email protected]e44de5d2009-06-05 20:12:451439 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441440
[email protected]5695b8c2009-09-30 21:36:431441 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441442
[email protected]1c773ea12009-04-28 19:58:421443 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441444 request.method = "GET";
1445 request.url = GURL("https://www.google.com/");
1446 request.load_flags = 0;
1447
1448 // Since we have proxy, should try to establish tunnel.
1449 MockWrite data_writes[] = {
1450 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451451 "Host: www.google.com\r\n"
1452 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441453 };
1454
1455 // The proxy responds to the connect with a 407.
1456 MockRead data_reads[] = {
1457 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1458 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1459 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421460 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441461 };
1462
[email protected]31a2bfe2010-02-09 08:03:391463 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1464 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591465 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441466
1467 TestCompletionCallback callback;
1468
[email protected]5a1d7ca2010-04-28 20:12:271469 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421470 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441471
1472 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421473 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441474
[email protected]1c773ea12009-04-28 19:58:421475 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441476 EXPECT_FALSE(response == NULL);
1477
1478 EXPECT_TRUE(response->headers->IsKeepAlive());
1479 EXPECT_EQ(407, response->headers->response_code());
1480 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421481 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441482
1483 std::string response_data;
1484 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421485 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181486
1487 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1488 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441489}
1490
[email protected]8fdbcd22010-05-05 02:54:521491// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1492// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1493TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1494 // We are using a DIRECT connection (i.e. no proxy) for this session.
1495 SessionDependencies session_deps;
1496 scoped_ptr<HttpTransaction> trans(
1497 new HttpNetworkTransaction(CreateSession(&session_deps)));
1498
1499 HttpRequestInfo request;
1500 request.method = "GET";
1501 request.url = GURL("http://www.google.com/");
1502 request.load_flags = 0;
1503
1504 MockWrite data_writes1[] = {
1505 MockWrite("GET / HTTP/1.1\r\n"
1506 "Host: www.google.com\r\n"
1507 "Connection: keep-alive\r\n\r\n"),
1508 };
1509
1510 MockRead data_reads1[] = {
1511 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1512 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1513 // Large content-length -- won't matter, as connection will be reset.
1514 MockRead("Content-Length: 10000\r\n\r\n"),
1515 MockRead(false, ERR_FAILED),
1516 };
1517
1518 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1519 data_writes1, arraysize(data_writes1));
1520 session_deps.socket_factory.AddSocketDataProvider(&data1);
1521
1522 TestCompletionCallback callback;
1523
1524 int rv = trans->Start(&request, &callback, BoundNetLog());
1525 EXPECT_EQ(ERR_IO_PENDING, rv);
1526
1527 rv = callback.WaitForResult();
1528 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1529}
1530
[email protected]ff007e162009-05-23 09:13:151531void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081532 const MockRead& status, int expected_status) {
1533 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591534 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081535
[email protected]228ff742009-06-05 01:19:591536 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081537
[email protected]5695b8c2009-09-30 21:36:431538 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081539
[email protected]1c773ea12009-04-28 19:58:421540 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081541 request.method = "GET";
1542 request.url = GURL("https://www.google.com/");
1543 request.load_flags = 0;
1544
1545 // Since we have proxy, should try to establish tunnel.
1546 MockWrite data_writes[] = {
1547 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451548 "Host: www.google.com\r\n"
1549 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081550 };
1551
1552 MockRead data_reads[] = {
1553 status,
1554 MockRead("Content-Length: 10\r\n\r\n"),
1555 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421556 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081557 };
1558
[email protected]31a2bfe2010-02-09 08:03:391559 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1560 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591561 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081562
1563 TestCompletionCallback callback;
1564
[email protected]5a1d7ca2010-04-28 20:12:271565 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421566 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081567
1568 rv = callback.WaitForResult();
1569 EXPECT_EQ(expected_status, rv);
1570}
1571
[email protected]ff007e162009-05-23 09:13:151572void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081573 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421574 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081575}
1576
1577TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1578 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1579}
1580
1581TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1582 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1583}
1584
1585TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1586 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1587}
1588
1589TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1590 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1591}
1592
1593TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1594 ConnectStatusHelper(
1595 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1596}
1597
1598TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1599 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1600}
1601
1602TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1603 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1604}
1605
1606TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1607 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1608}
1609
1610TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1611 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1612}
1613
1614TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1615 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1616}
1617
1618TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1619 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1620}
1621
1622TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1623 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1624}
1625
1626TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1627 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1628}
1629
1630TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1631 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1632}
1633
1634TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1635 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1636}
1637
1638TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1639 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1640}
1641
1642TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1643 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1644}
1645
1646TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1647 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1648}
1649
1650TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1651 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1652}
1653
1654TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1655 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1656}
1657
1658TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1659 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1660}
1661
1662TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1663 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1664}
1665
1666TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1667 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1668}
1669
1670TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1671 ConnectStatusHelperWithExpectedStatus(
1672 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:541673 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:081674}
1675
1676TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1677 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1678}
1679
1680TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1681 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1682}
1683
1684TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1685 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1686}
1687
1688TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1689 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1690}
1691
1692TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1693 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1694}
1695
1696TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1697 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1698}
1699
1700TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1701 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1702}
1703
1704TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1705 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1706}
1707
1708TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1709 ConnectStatusHelper(
1710 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1711}
1712
1713TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1714 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1715}
1716
1717TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1718 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1719}
1720
1721TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1722 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1723}
1724
1725TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1726 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1727}
1728
1729TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1730 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1731}
1732
1733TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1734 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1735}
1736
1737TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1738 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1739}
1740
[email protected]038e9a32008-10-08 22:40:161741// Test the flow when both the proxy server AND origin server require
1742// authentication. Again, this uses basic auth for both since that is
1743// the simplest to mock.
1744TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591745 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011746
[email protected]038e9a32008-10-08 22:40:161747 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421748 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431749 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161750
[email protected]1c773ea12009-04-28 19:58:421751 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161752 request.method = "GET";
1753 request.url = GURL("http://www.google.com/");
1754 request.load_flags = 0;
1755
[email protected]f9ee6b52008-11-08 06:46:231756 MockWrite data_writes1[] = {
1757 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1758 "Host: www.google.com\r\n"
1759 "Proxy-Connection: keep-alive\r\n\r\n"),
1760 };
1761
[email protected]038e9a32008-10-08 22:40:161762 MockRead data_reads1[] = {
1763 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1764 // Give a couple authenticate options (only the middle one is actually
1765 // supported).
[email protected]22927ad2009-09-21 19:56:191766 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161767 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1768 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1769 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1770 // Large content-length -- won't matter, as connection will be reset.
1771 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421772 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161773 };
1774
1775 // After calling trans->RestartWithAuth() the first time, this is the
1776 // request we should be issuing -- the final header line contains the
1777 // proxy's credentials.
1778 MockWrite data_writes2[] = {
1779 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1780 "Host: www.google.com\r\n"
1781 "Proxy-Connection: keep-alive\r\n"
1782 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1783 };
1784
1785 // Now the proxy server lets the request pass through to origin server.
1786 // The origin server responds with a 401.
1787 MockRead data_reads2[] = {
1788 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1789 // Note: We are using the same realm-name as the proxy server. This is
1790 // completely valid, as realms are unique across hosts.
1791 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1792 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1793 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421794 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161795 };
1796
1797 // After calling trans->RestartWithAuth() the second time, we should send
1798 // the credentials for both the proxy and origin server.
1799 MockWrite data_writes3[] = {
1800 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1801 "Host: www.google.com\r\n"
1802 "Proxy-Connection: keep-alive\r\n"
1803 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1804 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1805 };
1806
1807 // Lastly we get the desired content.
1808 MockRead data_reads3[] = {
1809 MockRead("HTTP/1.0 200 OK\r\n"),
1810 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1811 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421812 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161813 };
1814
[email protected]31a2bfe2010-02-09 08:03:391815 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1816 data_writes1, arraysize(data_writes1));
1817 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1818 data_writes2, arraysize(data_writes2));
1819 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1820 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591821 session_deps.socket_factory.AddSocketDataProvider(&data1);
1822 session_deps.socket_factory.AddSocketDataProvider(&data2);
1823 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161824
1825 TestCompletionCallback callback1;
1826
[email protected]5a1d7ca2010-04-28 20:12:271827 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421828 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161829
1830 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421831 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161832
[email protected]1c773ea12009-04-28 19:58:421833 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161834 EXPECT_FALSE(response == NULL);
1835
1836 // The password prompt info should have been set in response->auth_challenge.
1837 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1838
[email protected]71e4573a2009-05-21 22:03:001839 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161840 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1841 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1842
1843 TestCompletionCallback callback2;
1844
1845 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421846 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161847
1848 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421849 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161850
1851 response = trans->GetResponseInfo();
1852 EXPECT_FALSE(response == NULL);
1853 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1854
[email protected]71e4573a2009-05-21 22:03:001855 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161856 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1857 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1858
1859 TestCompletionCallback callback3;
1860
1861 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421862 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161863
1864 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421865 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161866
1867 response = trans->GetResponseInfo();
1868 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1869 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161870}
[email protected]4ddaf2502008-10-23 18:26:191871
[email protected]ea9dc9a2009-09-05 00:43:321872// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1873// can't hook into its internals to cause it to generate predictable NTLM
1874// authorization headers.
1875#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291876// The NTLM authentication unit tests were generated by capturing the HTTP
1877// requests and responses using Fiddler 2 and inspecting the generated random
1878// bytes in the debugger.
1879
1880// Enter the correct password and authenticate successfully.
1881TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421882 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:111883 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591884 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401885 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431886 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241887
[email protected]1c773ea12009-04-28 19:58:421888 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241889 request.method = "GET";
1890 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1891 request.load_flags = 0;
1892
1893 MockWrite data_writes1[] = {
1894 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1895 "Host: 172.22.68.17\r\n"
1896 "Connection: keep-alive\r\n\r\n"),
1897 };
1898
1899 MockRead data_reads1[] = {
1900 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:041901 // Negotiate and NTLM are often requested together. However, we only want
1902 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
1903 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:241904 MockRead("WWW-Authenticate: NTLM\r\n"),
1905 MockRead("Connection: close\r\n"),
1906 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361907 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241908 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421909 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241910 };
1911
1912 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221913 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241914 // request we should be issuing -- the final header line contains a Type
1915 // 1 message.
1916 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1917 "Host: 172.22.68.17\r\n"
1918 "Connection: keep-alive\r\n"
1919 "Authorization: NTLM "
1920 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1921
1922 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1923 // (the credentials for the origin server). The second request continues
1924 // on the same connection.
1925 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1926 "Host: 172.22.68.17\r\n"
1927 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291928 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1929 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1930 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1931 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1932 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241933 };
1934
1935 MockRead data_reads2[] = {
1936 // The origin server responds with a Type 2 message.
1937 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1938 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291939 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241940 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1941 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1942 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1943 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1944 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1945 "BtAAAAAAA=\r\n"),
1946 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361947 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241948 MockRead("You are not authorized to view this page\r\n"),
1949
1950 // Lastly we get the desired content.
1951 MockRead("HTTP/1.1 200 OK\r\n"),
1952 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1953 MockRead("Content-Length: 13\r\n\r\n"),
1954 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421955 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241956 };
1957
[email protected]31a2bfe2010-02-09 08:03:391958 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1959 data_writes1, arraysize(data_writes1));
1960 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1961 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591962 session_deps.socket_factory.AddSocketDataProvider(&data1);
1963 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241964
1965 TestCompletionCallback callback1;
1966
[email protected]5a1d7ca2010-04-28 20:12:271967 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421968 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241969
1970 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421971 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241972
[email protected]0757e7702009-03-27 04:00:221973 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1974 TestCompletionCallback callback2;
1975 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421976 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221977 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421978 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221979 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1980
[email protected]1c773ea12009-04-28 19:58:421981 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:041982 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:241983
[email protected]aef04272010-06-28 18:03:041984 // The password prompt info should have been set in
1985 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:241986 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1987
[email protected]71e4573a2009-05-21 22:03:001988 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241989 EXPECT_EQ(L"", response->auth_challenge->realm);
1990 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1991
[email protected]0757e7702009-03-27 04:00:221992 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241993
[email protected]0757e7702009-03-27 04:00:221994 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421995 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241996
[email protected]0757e7702009-03-27 04:00:221997 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421998 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241999
2000 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042001 ASSERT_FALSE(response == NULL);
2002
[email protected]3f918782009-02-28 01:29:242003 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2004 EXPECT_EQ(13, response->headers->GetContentLength());
2005}
2006
[email protected]385a4672009-03-11 22:21:292007// Enter a wrong password, and then the correct one.
2008TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422009 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112010 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592011 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402012 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432013 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:292014
[email protected]1c773ea12009-04-28 19:58:422015 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292016 request.method = "GET";
2017 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2018 request.load_flags = 0;
2019
2020 MockWrite data_writes1[] = {
2021 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2022 "Host: 172.22.68.17\r\n"
2023 "Connection: keep-alive\r\n\r\n"),
2024 };
2025
2026 MockRead data_reads1[] = {
2027 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042028 // Negotiate and NTLM are often requested together. However, we only want
2029 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2030 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292031 MockRead("WWW-Authenticate: NTLM\r\n"),
2032 MockRead("Connection: close\r\n"),
2033 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362034 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292035 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422036 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292037 };
2038
2039 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222040 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292041 // request we should be issuing -- the final header line contains a Type
2042 // 1 message.
2043 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2044 "Host: 172.22.68.17\r\n"
2045 "Connection: keep-alive\r\n"
2046 "Authorization: NTLM "
2047 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2048
2049 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2050 // (the credentials for the origin server). The second request continues
2051 // on the same connection.
2052 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2053 "Host: 172.22.68.17\r\n"
2054 "Connection: keep-alive\r\n"
2055 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2056 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2057 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2058 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2059 "4Ww7b7E=\r\n\r\n"),
2060 };
2061
2062 MockRead data_reads2[] = {
2063 // The origin server responds with a Type 2 message.
2064 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2065 MockRead("WWW-Authenticate: NTLM "
2066 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2067 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2068 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2069 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2070 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2071 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2072 "BtAAAAAAA=\r\n"),
2073 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362074 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292075 MockRead("You are not authorized to view this page\r\n"),
2076
2077 // Wrong password.
2078 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292079 MockRead("WWW-Authenticate: NTLM\r\n"),
2080 MockRead("Connection: close\r\n"),
2081 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362082 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292083 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422084 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292085 };
2086
2087 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222088 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292089 // request we should be issuing -- the final header line contains a Type
2090 // 1 message.
2091 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2092 "Host: 172.22.68.17\r\n"
2093 "Connection: keep-alive\r\n"
2094 "Authorization: NTLM "
2095 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2096
2097 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2098 // (the credentials for the origin server). The second request continues
2099 // on the same connection.
2100 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2101 "Host: 172.22.68.17\r\n"
2102 "Connection: keep-alive\r\n"
2103 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2104 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2105 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2106 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2107 "+4MUm7c=\r\n\r\n"),
2108 };
2109
2110 MockRead data_reads3[] = {
2111 // The origin server responds with a Type 2 message.
2112 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2113 MockRead("WWW-Authenticate: NTLM "
2114 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2115 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2116 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2117 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2118 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2119 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2120 "BtAAAAAAA=\r\n"),
2121 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362122 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292123 MockRead("You are not authorized to view this page\r\n"),
2124
2125 // Lastly we get the desired content.
2126 MockRead("HTTP/1.1 200 OK\r\n"),
2127 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2128 MockRead("Content-Length: 13\r\n\r\n"),
2129 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422130 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292131 };
2132
[email protected]31a2bfe2010-02-09 08:03:392133 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2134 data_writes1, arraysize(data_writes1));
2135 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2136 data_writes2, arraysize(data_writes2));
2137 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2138 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592139 session_deps.socket_factory.AddSocketDataProvider(&data1);
2140 session_deps.socket_factory.AddSocketDataProvider(&data2);
2141 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292142
2143 TestCompletionCallback callback1;
2144
[email protected]5a1d7ca2010-04-28 20:12:272145 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422146 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292147
2148 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422149 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292150
[email protected]0757e7702009-03-27 04:00:222151 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292152 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:222153 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422154 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292155 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422156 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222157 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292158
[email protected]1c773ea12009-04-28 19:58:422159 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292160 EXPECT_FALSE(response == NULL);
2161
2162 // The password prompt info should have been set in response->auth_challenge.
2163 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2164
[email protected]71e4573a2009-05-21 22:03:002165 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292166 EXPECT_EQ(L"", response->auth_challenge->realm);
2167 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2168
2169 TestCompletionCallback callback3;
2170
[email protected]0757e7702009-03-27 04:00:222171 // Enter the wrong password.
2172 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:422173 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292174
2175 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422176 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292177
[email protected]0757e7702009-03-27 04:00:222178 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2179 TestCompletionCallback callback4;
2180 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422181 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222182 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422183 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222184 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2185
2186 response = trans->GetResponseInfo();
2187 EXPECT_FALSE(response == NULL);
2188
2189 // The password prompt info should have been set in response->auth_challenge.
2190 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2191
[email protected]71e4573a2009-05-21 22:03:002192 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222193 EXPECT_EQ(L"", response->auth_challenge->realm);
2194 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2195
2196 TestCompletionCallback callback5;
2197
2198 // Now enter the right password.
2199 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422200 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222201
2202 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422203 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222204
[email protected]385a4672009-03-11 22:21:292205 response = trans->GetResponseInfo();
2206 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2207 EXPECT_EQ(13, response->headers->GetContentLength());
2208}
[email protected]ea9dc9a2009-09-05 00:43:322209#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292210
[email protected]4ddaf2502008-10-23 18:26:192211// Test reading a server response which has only headers, and no body.
2212// After some maximum number of bytes is consumed, the transaction should
2213// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2214TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592215 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402216 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432217 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192218
[email protected]1c773ea12009-04-28 19:58:422219 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192220 request.method = "GET";
2221 request.url = GURL("http://www.google.com/");
2222 request.load_flags = 0;
2223
[email protected]b75b7b2f2009-10-06 00:54:532224 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432225 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532226 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192227
2228 MockRead data_reads[] = {
2229 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432230 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192231 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422232 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192233 };
[email protected]31a2bfe2010-02-09 08:03:392234 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592235 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192236
2237 TestCompletionCallback callback;
2238
[email protected]5a1d7ca2010-04-28 20:12:272239 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422240 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192241
2242 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422243 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192244
[email protected]1c773ea12009-04-28 19:58:422245 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192246 EXPECT_TRUE(response == NULL);
2247}
[email protected]f4e426b2008-11-05 00:24:492248
2249// Make sure that we don't try to reuse a TCPClientSocket when failing to
2250// establish tunnel.
2251// http://code.google.com/p/chromium/issues/detail?id=3772
2252TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2253 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592254 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012255
[email protected]228ff742009-06-05 01:19:592256 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492257
[email protected]5695b8c2009-09-30 21:36:432258 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492259
[email protected]1c773ea12009-04-28 19:58:422260 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492261 request.method = "GET";
2262 request.url = GURL("https://www.google.com/");
2263 request.load_flags = 0;
2264
2265 // Since we have proxy, should try to establish tunnel.
2266 MockWrite data_writes1[] = {
2267 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452268 "Host: www.google.com\r\n"
2269 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492270 };
2271
[email protected]77848d12008-11-14 00:00:222272 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492273 // connection. Usually a proxy would return 501 (not implemented),
2274 // or 200 (tunnel established).
2275 MockRead data_reads1[] = {
2276 MockRead("HTTP/1.1 404 Not Found\r\n"),
2277 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422278 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492279 };
2280
[email protected]31a2bfe2010-02-09 08:03:392281 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2282 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592283 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492284
2285 TestCompletionCallback callback1;
2286
[email protected]5a1d7ca2010-04-28 20:12:272287 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422288 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492289
2290 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422291 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492292
[email protected]1c773ea12009-04-28 19:58:422293 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082294 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492295
[email protected]b4404c02009-04-10 16:38:522296 // Empty the current queue. This is necessary because idle sockets are
2297 // added to the connection pool asynchronously with a PostTask.
2298 MessageLoop::current()->RunAllPending();
2299
[email protected]f4e426b2008-11-05 00:24:492300 // We now check to make sure the TCPClientSocket was not added back to
2301 // the pool.
[email protected]a937a06d2009-08-19 21:19:242302 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492303 trans.reset();
[email protected]b4404c02009-04-10 16:38:522304 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492305 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242306 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492307}
[email protected]372d34a2008-11-05 21:30:512308
[email protected]1b157c02009-04-21 01:55:402309// Make sure that we recycle a socket after reading all of the response body.
2310TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592311 SessionDependencies session_deps;
2312 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402313
[email protected]5695b8c2009-09-30 21:36:432314 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402315
[email protected]1c773ea12009-04-28 19:58:422316 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402317 request.method = "GET";
2318 request.url = GURL("http://www.google.com/");
2319 request.load_flags = 0;
2320
2321 MockRead data_reads[] = {
2322 // A part of the response body is received with the response headers.
2323 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2324 // The rest of the response body is received in two parts.
2325 MockRead("lo"),
2326 MockRead(" world"),
2327 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422328 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402329 };
2330
[email protected]31a2bfe2010-02-09 08:03:392331 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592332 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402333
2334 TestCompletionCallback callback;
2335
[email protected]5a1d7ca2010-04-28 20:12:272336 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422337 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402338
2339 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422340 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402341
[email protected]1c773ea12009-04-28 19:58:422342 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402343 EXPECT_TRUE(response != NULL);
2344
2345 EXPECT_TRUE(response->headers != NULL);
2346 std::string status_line = response->headers->GetStatusLine();
2347 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2348
[email protected]a937a06d2009-08-19 21:19:242349 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402350
2351 std::string response_data;
2352 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422353 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402354 EXPECT_EQ("hello world", response_data);
2355
2356 // Empty the current queue. This is necessary because idle sockets are
2357 // added to the connection pool asynchronously with a PostTask.
2358 MessageLoop::current()->RunAllPending();
2359
2360 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242361 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402362}
2363
[email protected]b4404c02009-04-10 16:38:522364// Make sure that we recycle a socket after a zero-length response.
2365// http://crbug.com/9880
2366TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592367 SessionDependencies session_deps;
2368 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522369
[email protected]5695b8c2009-09-30 21:36:432370 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522371
[email protected]1c773ea12009-04-28 19:58:422372 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522373 request.method = "GET";
2374 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2375 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2376 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2377 "rt=prt.2642,ol.2649,xjs.2951");
2378 request.load_flags = 0;
2379
2380 MockRead data_reads[] = {
2381 MockRead("HTTP/1.1 204 No Content\r\n"
2382 "Content-Length: 0\r\n"
2383 "Content-Type: text/html\r\n\r\n"),
2384 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422385 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522386 };
2387
[email protected]31a2bfe2010-02-09 08:03:392388 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592389 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522390
2391 TestCompletionCallback callback;
2392
[email protected]5a1d7ca2010-04-28 20:12:272393 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422394 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522395
2396 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422397 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522398
[email protected]1c773ea12009-04-28 19:58:422399 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522400 EXPECT_TRUE(response != NULL);
2401
2402 EXPECT_TRUE(response->headers != NULL);
2403 std::string status_line = response->headers->GetStatusLine();
2404 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2405
[email protected]a937a06d2009-08-19 21:19:242406 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522407
2408 std::string response_data;
2409 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422410 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522411 EXPECT_EQ("", response_data);
2412
2413 // Empty the current queue. This is necessary because idle sockets are
2414 // added to the connection pool asynchronously with a PostTask.
2415 MessageLoop::current()->RunAllPending();
2416
2417 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242418 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522419}
2420
[email protected]372d34a2008-11-05 21:30:512421TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422422 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512423 // Transaction 1: a GET request that succeeds. The socket is recycled
2424 // after use.
2425 request[0].method = "GET";
2426 request[0].url = GURL("http://www.google.com/");
2427 request[0].load_flags = 0;
2428 // Transaction 2: a POST request. Reuses the socket kept alive from
2429 // transaction 1. The first attempts fails when writing the POST data.
2430 // This causes the transaction to retry with a new socket. The second
2431 // attempt succeeds.
2432 request[1].method = "POST";
2433 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422434 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512435 request[1].upload_data->AppendBytes("foo", 3);
2436 request[1].load_flags = 0;
2437
[email protected]228ff742009-06-05 01:19:592438 SessionDependencies session_deps;
2439 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512440
2441 // The first socket is used for transaction 1 and the first attempt of
2442 // transaction 2.
2443
2444 // The response of transaction 1.
2445 MockRead data_reads1[] = {
2446 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2447 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422448 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512449 };
2450 // The mock write results of transaction 1 and the first attempt of
2451 // transaction 2.
2452 MockWrite data_writes1[] = {
2453 MockWrite(false, 64), // GET
2454 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422455 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512456 };
[email protected]31a2bfe2010-02-09 08:03:392457 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2458 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512459
2460 // The second socket is used for the second attempt of transaction 2.
2461
2462 // The response of transaction 2.
2463 MockRead data_reads2[] = {
2464 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2465 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422466 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512467 };
2468 // The mock write results of the second attempt of transaction 2.
2469 MockWrite data_writes2[] = {
2470 MockWrite(false, 93), // POST
2471 MockWrite(false, 3), // POST data
2472 };
[email protected]31a2bfe2010-02-09 08:03:392473 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2474 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512475
[email protected]5ecc992a42009-11-11 01:41:592476 session_deps.socket_factory.AddSocketDataProvider(&data1);
2477 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512478
2479 const char* kExpectedResponseData[] = {
2480 "hello world", "welcome"
2481 };
2482
2483 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422484 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432485 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512486
2487 TestCompletionCallback callback;
2488
[email protected]5a1d7ca2010-04-28 20:12:272489 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422490 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512491
2492 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422493 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512494
[email protected]1c773ea12009-04-28 19:58:422495 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512496 EXPECT_TRUE(response != NULL);
2497
2498 EXPECT_TRUE(response->headers != NULL);
2499 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2500
2501 std::string response_data;
2502 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422503 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512504 EXPECT_EQ(kExpectedResponseData[i], response_data);
2505 }
2506}
[email protected]f9ee6b52008-11-08 06:46:232507
2508// Test the request-challenge-retry sequence for basic auth when there is
2509// an identity in the URL. The request should be sent as normal, but when
2510// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322511TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592512 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402513 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432514 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232515
[email protected]1c773ea12009-04-28 19:58:422516 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232517 request.method = "GET";
2518 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292519 request.url = GURL("http://foo:b@[email protected]/");
2520
2521 // The password contains an escaped character -- for this test to pass it
2522 // will need to be unescaped by HttpNetworkTransaction.
2523 EXPECT_EQ("b%40r", request.url.password());
2524
[email protected]ea9dc9a2009-09-05 00:43:322525 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232526
2527 MockWrite data_writes1[] = {
2528 MockWrite("GET / HTTP/1.1\r\n"
2529 "Host: www.google.com\r\n"
2530 "Connection: keep-alive\r\n\r\n"),
2531 };
2532
2533 MockRead data_reads1[] = {
2534 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2535 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2536 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422537 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232538 };
2539
2540 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322541 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232542 MockWrite data_writes2[] = {
2543 MockWrite("GET / HTTP/1.1\r\n"
2544 "Host: www.google.com\r\n"
2545 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292546 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232547 };
2548
2549 MockRead data_reads2[] = {
2550 MockRead("HTTP/1.0 200 OK\r\n"),
2551 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422552 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232553 };
2554
[email protected]31a2bfe2010-02-09 08:03:392555 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2556 data_writes1, arraysize(data_writes1));
2557 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2558 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592559 session_deps.socket_factory.AddSocketDataProvider(&data1);
2560 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232561
2562 TestCompletionCallback callback1;
2563
[email protected]5a1d7ca2010-04-28 20:12:272564 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422565 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232566
2567 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422568 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232569
[email protected]0757e7702009-03-27 04:00:222570 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2571 TestCompletionCallback callback2;
2572 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422573 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222574 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422575 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222576 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2577
[email protected]1c773ea12009-04-28 19:58:422578 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232579 EXPECT_FALSE(response == NULL);
2580
2581 // There is no challenge info, since the identity in URL worked.
2582 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2583
2584 EXPECT_EQ(100, response->headers->GetContentLength());
2585
2586 // Empty the current queue.
2587 MessageLoop::current()->RunAllPending();
2588}
2589
[email protected]ea9dc9a2009-09-05 00:43:322590// Test the request-challenge-retry sequence for basic auth when there is
2591// an incorrect identity in the URL. The identity from the URL should be used
2592// only once.
2593TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2594 SessionDependencies session_deps;
2595 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432596 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322597
2598 HttpRequestInfo request;
2599 request.method = "GET";
2600 // Note: the URL has a username:password in it. The password "baz" is
2601 // wrong (should be "bar").
2602 request.url = GURL("http://foo:[email protected]/");
2603
2604 request.load_flags = LOAD_NORMAL;
2605
2606 MockWrite data_writes1[] = {
2607 MockWrite("GET / HTTP/1.1\r\n"
2608 "Host: www.google.com\r\n"
2609 "Connection: keep-alive\r\n\r\n"),
2610 };
2611
2612 MockRead data_reads1[] = {
2613 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2614 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2615 MockRead("Content-Length: 10\r\n\r\n"),
2616 MockRead(false, ERR_FAILED),
2617 };
2618
2619 // After the challenge above, the transaction will be restarted using the
2620 // identity from the url (foo, baz) to answer the challenge.
2621 MockWrite data_writes2[] = {
2622 MockWrite("GET / HTTP/1.1\r\n"
2623 "Host: www.google.com\r\n"
2624 "Connection: keep-alive\r\n"
2625 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2626 };
2627
2628 MockRead data_reads2[] = {
2629 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2630 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2631 MockRead("Content-Length: 10\r\n\r\n"),
2632 MockRead(false, ERR_FAILED),
2633 };
2634
2635 // After the challenge above, the transaction will be restarted using the
2636 // identity supplied by the user (foo, bar) to answer the challenge.
2637 MockWrite data_writes3[] = {
2638 MockWrite("GET / HTTP/1.1\r\n"
2639 "Host: www.google.com\r\n"
2640 "Connection: keep-alive\r\n"
2641 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2642 };
2643
2644 MockRead data_reads3[] = {
2645 MockRead("HTTP/1.0 200 OK\r\n"),
2646 MockRead("Content-Length: 100\r\n\r\n"),
2647 MockRead(false, OK),
2648 };
2649
[email protected]31a2bfe2010-02-09 08:03:392650 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2651 data_writes1, arraysize(data_writes1));
2652 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2653 data_writes2, arraysize(data_writes2));
2654 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2655 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592656 session_deps.socket_factory.AddSocketDataProvider(&data1);
2657 session_deps.socket_factory.AddSocketDataProvider(&data2);
2658 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322659
2660 TestCompletionCallback callback1;
2661
[email protected]5a1d7ca2010-04-28 20:12:272662 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322663 EXPECT_EQ(ERR_IO_PENDING, rv);
2664
2665 rv = callback1.WaitForResult();
2666 EXPECT_EQ(OK, rv);
2667
2668 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2669 TestCompletionCallback callback2;
2670 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2671 EXPECT_EQ(ERR_IO_PENDING, rv);
2672 rv = callback2.WaitForResult();
2673 EXPECT_EQ(OK, rv);
2674 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2675
2676 const HttpResponseInfo* response = trans->GetResponseInfo();
2677 EXPECT_FALSE(response == NULL);
2678 // The password prompt info should have been set in response->auth_challenge.
2679 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2680
2681 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2682 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2683 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2684
2685 TestCompletionCallback callback3;
2686 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2687 EXPECT_EQ(ERR_IO_PENDING, rv);
2688 rv = callback3.WaitForResult();
2689 EXPECT_EQ(OK, rv);
2690 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2691
2692 response = trans->GetResponseInfo();
2693 EXPECT_FALSE(response == NULL);
2694
2695 // There is no challenge info, since the identity worked.
2696 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2697
2698 EXPECT_EQ(100, response->headers->GetContentLength());
2699
2700 // Empty the current queue.
2701 MessageLoop::current()->RunAllPending();
2702}
2703
[email protected]f9ee6b52008-11-08 06:46:232704// Test that previously tried username/passwords for a realm get re-used.
2705TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592706 SessionDependencies session_deps;
2707 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232708
2709 // Transaction 1: authenticate (foo, bar) on MyRealm1
2710 {
[email protected]5695b8c2009-09-30 21:36:432711 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232712
[email protected]1c773ea12009-04-28 19:58:422713 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232714 request.method = "GET";
2715 request.url = GURL("http://www.google.com/x/y/z");
2716 request.load_flags = 0;
2717
2718 MockWrite data_writes1[] = {
2719 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2720 "Host: www.google.com\r\n"
2721 "Connection: keep-alive\r\n\r\n"),
2722 };
2723
2724 MockRead data_reads1[] = {
2725 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2726 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2727 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422728 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232729 };
2730
2731 // Resend with authorization (username=foo, password=bar)
2732 MockWrite data_writes2[] = {
2733 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2734 "Host: www.google.com\r\n"
2735 "Connection: keep-alive\r\n"
2736 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2737 };
2738
2739 // Sever accepts the authorization.
2740 MockRead data_reads2[] = {
2741 MockRead("HTTP/1.0 200 OK\r\n"),
2742 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422743 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232744 };
2745
[email protected]31a2bfe2010-02-09 08:03:392746 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2747 data_writes1, arraysize(data_writes1));
2748 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2749 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592750 session_deps.socket_factory.AddSocketDataProvider(&data1);
2751 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232752
2753 TestCompletionCallback callback1;
2754
[email protected]5a1d7ca2010-04-28 20:12:272755 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422756 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232757
2758 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422759 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232760
[email protected]1c773ea12009-04-28 19:58:422761 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232762 EXPECT_FALSE(response == NULL);
2763
2764 // The password prompt info should have been set in
2765 // response->auth_challenge.
2766 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2767
[email protected]71e4573a2009-05-21 22:03:002768 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232769 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2770 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2771
2772 TestCompletionCallback callback2;
2773
2774 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422775 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232776
2777 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422778 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232779
2780 response = trans->GetResponseInfo();
2781 EXPECT_FALSE(response == NULL);
2782 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2783 EXPECT_EQ(100, response->headers->GetContentLength());
2784 }
2785
2786 // ------------------------------------------------------------------------
2787
2788 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2789 {
[email protected]5695b8c2009-09-30 21:36:432790 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232791
[email protected]1c773ea12009-04-28 19:58:422792 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232793 request.method = "GET";
2794 // Note that Transaction 1 was at /x/y/z, so this is in the same
2795 // protection space as MyRealm1.
2796 request.url = GURL("http://www.google.com/x/y/a/b");
2797 request.load_flags = 0;
2798
2799 MockWrite data_writes1[] = {
2800 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2801 "Host: www.google.com\r\n"
2802 "Connection: keep-alive\r\n"
2803 // Send preemptive authorization for MyRealm1
2804 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2805 };
2806
2807 // The server didn't like the preemptive authorization, and
2808 // challenges us for a different realm (MyRealm2).
2809 MockRead data_reads1[] = {
2810 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2811 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2812 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422813 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232814 };
2815
2816 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2817 MockWrite data_writes2[] = {
2818 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2819 "Host: www.google.com\r\n"
2820 "Connection: keep-alive\r\n"
2821 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2822 };
2823
2824 // Sever accepts the authorization.
2825 MockRead data_reads2[] = {
2826 MockRead("HTTP/1.0 200 OK\r\n"),
2827 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422828 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232829 };
2830
[email protected]31a2bfe2010-02-09 08:03:392831 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2832 data_writes1, arraysize(data_writes1));
2833 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2834 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592835 session_deps.socket_factory.AddSocketDataProvider(&data1);
2836 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232837
2838 TestCompletionCallback callback1;
2839
[email protected]5a1d7ca2010-04-28 20:12:272840 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422841 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232842
2843 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422844 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232845
[email protected]1c773ea12009-04-28 19:58:422846 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232847 EXPECT_FALSE(response == NULL);
2848
2849 // The password prompt info should have been set in
2850 // response->auth_challenge.
2851 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2852
[email protected]71e4573a2009-05-21 22:03:002853 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232854 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2855 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2856
2857 TestCompletionCallback callback2;
2858
2859 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422860 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232861
2862 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422863 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232864
2865 response = trans->GetResponseInfo();
2866 EXPECT_FALSE(response == NULL);
2867 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2868 EXPECT_EQ(100, response->headers->GetContentLength());
2869 }
2870
2871 // ------------------------------------------------------------------------
2872
2873 // Transaction 3: Resend a request in MyRealm's protection space --
2874 // succeed with preemptive authorization.
2875 {
[email protected]5695b8c2009-09-30 21:36:432876 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232877
[email protected]1c773ea12009-04-28 19:58:422878 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232879 request.method = "GET";
2880 request.url = GURL("http://www.google.com/x/y/z2");
2881 request.load_flags = 0;
2882
2883 MockWrite data_writes1[] = {
2884 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2885 "Host: www.google.com\r\n"
2886 "Connection: keep-alive\r\n"
2887 // The authorization for MyRealm1 gets sent preemptively
2888 // (since the url is in the same protection space)
2889 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2890 };
2891
2892 // Sever accepts the preemptive authorization
2893 MockRead data_reads1[] = {
2894 MockRead("HTTP/1.0 200 OK\r\n"),
2895 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422896 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232897 };
2898
[email protected]31a2bfe2010-02-09 08:03:392899 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2900 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592901 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232902
2903 TestCompletionCallback callback1;
2904
[email protected]5a1d7ca2010-04-28 20:12:272905 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422906 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232907
2908 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422909 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232910
[email protected]1c773ea12009-04-28 19:58:422911 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232912 EXPECT_FALSE(response == NULL);
2913
2914 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2915 EXPECT_EQ(100, response->headers->GetContentLength());
2916 }
2917
2918 // ------------------------------------------------------------------------
2919
2920 // Transaction 4: request another URL in MyRealm (however the
2921 // url is not known to belong to the protection space, so no pre-auth).
2922 {
[email protected]5695b8c2009-09-30 21:36:432923 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232924
[email protected]1c773ea12009-04-28 19:58:422925 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232926 request.method = "GET";
2927 request.url = GURL("http://www.google.com/x/1");
2928 request.load_flags = 0;
2929
2930 MockWrite data_writes1[] = {
2931 MockWrite("GET /x/1 HTTP/1.1\r\n"
2932 "Host: www.google.com\r\n"
2933 "Connection: keep-alive\r\n\r\n"),
2934 };
2935
2936 MockRead data_reads1[] = {
2937 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2938 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2939 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422940 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232941 };
2942
2943 // Resend with authorization from MyRealm's cache.
2944 MockWrite data_writes2[] = {
2945 MockWrite("GET /x/1 HTTP/1.1\r\n"
2946 "Host: www.google.com\r\n"
2947 "Connection: keep-alive\r\n"
2948 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2949 };
2950
2951 // Sever accepts the authorization.
2952 MockRead data_reads2[] = {
2953 MockRead("HTTP/1.0 200 OK\r\n"),
2954 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422955 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232956 };
2957
[email protected]31a2bfe2010-02-09 08:03:392958 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2959 data_writes1, arraysize(data_writes1));
2960 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2961 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592962 session_deps.socket_factory.AddSocketDataProvider(&data1);
2963 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232964
2965 TestCompletionCallback callback1;
2966
[email protected]5a1d7ca2010-04-28 20:12:272967 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422968 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232969
2970 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422971 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232972
[email protected]0757e7702009-03-27 04:00:222973 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2974 TestCompletionCallback callback2;
2975 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422976 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222977 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422978 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222979 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2980
[email protected]1c773ea12009-04-28 19:58:422981 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232982 EXPECT_FALSE(response == NULL);
2983 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2984 EXPECT_EQ(100, response->headers->GetContentLength());
2985 }
2986
2987 // ------------------------------------------------------------------------
2988
2989 // Transaction 5: request a URL in MyRealm, but the server rejects the
2990 // cached identity. Should invalidate and re-prompt.
2991 {
[email protected]5695b8c2009-09-30 21:36:432992 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232993
[email protected]1c773ea12009-04-28 19:58:422994 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232995 request.method = "GET";
2996 request.url = GURL("http://www.google.com/p/q/t");
2997 request.load_flags = 0;
2998
2999 MockWrite data_writes1[] = {
3000 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3001 "Host: www.google.com\r\n"
3002 "Connection: keep-alive\r\n\r\n"),
3003 };
3004
3005 MockRead data_reads1[] = {
3006 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3007 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3008 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423009 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233010 };
3011
3012 // Resend with authorization from cache for MyRealm.
3013 MockWrite data_writes2[] = {
3014 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3015 "Host: www.google.com\r\n"
3016 "Connection: keep-alive\r\n"
3017 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3018 };
3019
3020 // Sever rejects the authorization.
3021 MockRead data_reads2[] = {
3022 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3023 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3024 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423025 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233026 };
3027
3028 // At this point we should prompt for new credentials for MyRealm.
3029 // Restart with username=foo3, password=foo4.
3030 MockWrite data_writes3[] = {
3031 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3032 "Host: www.google.com\r\n"
3033 "Connection: keep-alive\r\n"
3034 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3035 };
3036
3037 // Sever accepts the authorization.
3038 MockRead data_reads3[] = {
3039 MockRead("HTTP/1.0 200 OK\r\n"),
3040 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423041 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233042 };
3043
[email protected]31a2bfe2010-02-09 08:03:393044 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3045 data_writes1, arraysize(data_writes1));
3046 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3047 data_writes2, arraysize(data_writes2));
3048 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3049 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593050 session_deps.socket_factory.AddSocketDataProvider(&data1);
3051 session_deps.socket_factory.AddSocketDataProvider(&data2);
3052 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233053
3054 TestCompletionCallback callback1;
3055
[email protected]5a1d7ca2010-04-28 20:12:273056 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423057 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233058
3059 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423060 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233061
[email protected]0757e7702009-03-27 04:00:223062 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3063 TestCompletionCallback callback2;
3064 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423065 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223066 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423067 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223068 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3069
[email protected]1c773ea12009-04-28 19:58:423070 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233071 EXPECT_FALSE(response == NULL);
3072
3073 // The password prompt info should have been set in
3074 // response->auth_challenge.
3075 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3076
[email protected]71e4573a2009-05-21 22:03:003077 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233078 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3079 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3080
[email protected]0757e7702009-03-27 04:00:223081 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233082
[email protected]0757e7702009-03-27 04:00:223083 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:423084 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233085
[email protected]0757e7702009-03-27 04:00:223086 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423087 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233088
3089 response = trans->GetResponseInfo();
3090 EXPECT_FALSE(response == NULL);
3091 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3092 EXPECT_EQ(100, response->headers->GetContentLength());
3093 }
3094}
[email protected]89ceba9a2009-03-21 03:46:063095
[email protected]3c32c5f2010-05-18 15:18:123096// Tests that nonce count increments when multiple auth attempts
3097// are started with the same nonce.
3098TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3099 SessionDependencies session_deps;
3100 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3101 HttpAuthHandlerDigest::SetFixedCnonce(true);
3102
3103 // Transaction 1: authenticate (foo, bar) on MyRealm1
3104 {
3105 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3106
3107 HttpRequestInfo request;
3108 request.method = "GET";
3109 request.url = GURL("http://www.google.com/x/y/z");
3110 request.load_flags = 0;
3111
3112 MockWrite data_writes1[] = {
3113 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3114 "Host: www.google.com\r\n"
3115 "Connection: keep-alive\r\n\r\n"),
3116 };
3117
3118 MockRead data_reads1[] = {
3119 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3120 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3121 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3122 MockRead(false, OK),
3123 };
3124
3125 // Resend with authorization (username=foo, password=bar)
3126 MockWrite data_writes2[] = {
3127 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3128 "Host: www.google.com\r\n"
3129 "Connection: keep-alive\r\n"
3130 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3131 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3132 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3133 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3134 };
3135
3136 // Sever accepts the authorization.
3137 MockRead data_reads2[] = {
3138 MockRead("HTTP/1.0 200 OK\r\n"),
3139 MockRead(false, OK),
3140 };
3141
3142 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3143 data_writes1, arraysize(data_writes1));
3144 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3145 data_writes2, arraysize(data_writes2));
3146 session_deps.socket_factory.AddSocketDataProvider(&data1);
3147 session_deps.socket_factory.AddSocketDataProvider(&data2);
3148
3149 TestCompletionCallback callback1;
3150
3151 int rv = trans->Start(&request, &callback1, BoundNetLog());
3152 EXPECT_EQ(ERR_IO_PENDING, rv);
3153
3154 rv = callback1.WaitForResult();
3155 EXPECT_EQ(OK, rv);
3156
3157 const HttpResponseInfo* response = trans->GetResponseInfo();
3158 ASSERT_FALSE(response == NULL);
3159
3160 // The password prompt info should have been set in
3161 // response->auth_challenge.
3162 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3163
3164 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3165 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3166 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3167
3168 TestCompletionCallback callback2;
3169
3170 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3171 EXPECT_EQ(ERR_IO_PENDING, rv);
3172
3173 rv = callback2.WaitForResult();
3174 EXPECT_EQ(OK, rv);
3175
3176 response = trans->GetResponseInfo();
3177 ASSERT_FALSE(response == NULL);
3178 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3179 }
3180
3181 // ------------------------------------------------------------------------
3182
3183 // Transaction 2: Request another resource in digestive's protection space.
3184 // This will preemptively add an Authorization header which should have an
3185 // "nc" value of 2 (as compared to 1 in the first use.
3186 {
3187 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3188
3189 HttpRequestInfo request;
3190 request.method = "GET";
3191 // Note that Transaction 1 was at /x/y/z, so this is in the same
3192 // protection space as digest.
3193 request.url = GURL("http://www.google.com/x/y/a/b");
3194 request.load_flags = 0;
3195
3196 MockWrite data_writes1[] = {
3197 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3198 "Host: www.google.com\r\n"
3199 "Connection: keep-alive\r\n"
3200 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3201 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3202 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3203 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3204 };
3205
3206 // Sever accepts the authorization.
3207 MockRead data_reads1[] = {
3208 MockRead("HTTP/1.0 200 OK\r\n"),
3209 MockRead("Content-Length: 100\r\n\r\n"),
3210 MockRead(false, OK),
3211 };
3212
3213 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3214 data_writes1, arraysize(data_writes1));
3215 session_deps.socket_factory.AddSocketDataProvider(&data1);
3216
3217 TestCompletionCallback callback1;
3218
3219 int rv = trans->Start(&request, &callback1, BoundNetLog());
3220 EXPECT_EQ(ERR_IO_PENDING, rv);
3221
3222 rv = callback1.WaitForResult();
3223 EXPECT_EQ(OK, rv);
3224
3225 const HttpResponseInfo* response = trans->GetResponseInfo();
3226 ASSERT_FALSE(response == NULL);
3227 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3228 }
3229}
3230
[email protected]89ceba9a2009-03-21 03:46:063231// Test the ResetStateForRestart() private method.
3232TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3233 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593234 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403235 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433236 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063237
3238 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063239 trans->read_buf_ = new IOBuffer(15);
3240 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573241 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063242
3243 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143244 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573245 response->auth_challenge = new AuthChallengeInfo();
3246 response->ssl_info.cert_status = -15;
3247 response->response_time = base::Time::Now();
3248 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063249
3250 { // Setup state for response_.vary_data
3251 HttpRequestInfo request;
3252 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3253 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573254 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433255 request.extra_headers.SetHeader("Foo", "1");
3256 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573257 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063258 }
3259
3260 // Cause the above state to be reset.
3261 trans->ResetStateForRestart();
3262
3263 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073264 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063265 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573266 EXPECT_EQ(0U, trans->request_headers_.size());
3267 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3268 EXPECT_TRUE(response->headers.get() == NULL);
3269 EXPECT_EQ(false, response->was_cached);
3270 EXPECT_EQ(0, response->ssl_info.cert_status);
3271 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063272}
3273
[email protected]bacff652009-03-31 17:50:333274// Test HTTPS connections to a site with a bad certificate
3275TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593276 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403277 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433278 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333279
3280 HttpRequestInfo request;
3281 request.method = "GET";
3282 request.url = GURL("https://www.google.com/");
3283 request.load_flags = 0;
3284
3285 MockWrite data_writes[] = {
3286 MockWrite("GET / HTTP/1.1\r\n"
3287 "Host: www.google.com\r\n"
3288 "Connection: keep-alive\r\n\r\n"),
3289 };
3290
3291 MockRead data_reads[] = {
3292 MockRead("HTTP/1.0 200 OK\r\n"),
3293 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3294 MockRead("Content-Length: 100\r\n\r\n"),
3295 MockRead(false, OK),
3296 };
3297
[email protected]5ecc992a42009-11-11 01:41:593298 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393299 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3300 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593301 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3302 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333303
[email protected]5ecc992a42009-11-11 01:41:593304 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3305 session_deps.socket_factory.AddSocketDataProvider(&data);
3306 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3307 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333308
3309 TestCompletionCallback callback;
3310
[email protected]5a1d7ca2010-04-28 20:12:273311 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333312 EXPECT_EQ(ERR_IO_PENDING, rv);
3313
3314 rv = callback.WaitForResult();
3315 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3316
3317 rv = trans->RestartIgnoringLastError(&callback);
3318 EXPECT_EQ(ERR_IO_PENDING, rv);
3319
3320 rv = callback.WaitForResult();
3321 EXPECT_EQ(OK, rv);
3322
3323 const HttpResponseInfo* response = trans->GetResponseInfo();
3324
3325 EXPECT_FALSE(response == NULL);
3326 EXPECT_EQ(100, response->headers->GetContentLength());
3327}
3328
3329// Test HTTPS connections to a site with a bad certificate, going through a
3330// proxy
3331TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593332 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333333
3334 HttpRequestInfo request;
3335 request.method = "GET";
3336 request.url = GURL("https://www.google.com/");
3337 request.load_flags = 0;
3338
3339 MockWrite proxy_writes[] = {
3340 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453341 "Host: www.google.com\r\n"
3342 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333343 };
3344
3345 MockRead proxy_reads[] = {
3346 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423347 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333348 };
3349
3350 MockWrite data_writes[] = {
3351 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453352 "Host: www.google.com\r\n"
3353 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333354 MockWrite("GET / HTTP/1.1\r\n"
3355 "Host: www.google.com\r\n"
3356 "Connection: keep-alive\r\n\r\n"),
3357 };
3358
3359 MockRead data_reads[] = {
3360 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3361 MockRead("HTTP/1.0 200 OK\r\n"),
3362 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3363 MockRead("Content-Length: 100\r\n\r\n"),
3364 MockRead(false, OK),
3365 };
3366
[email protected]31a2bfe2010-02-09 08:03:393367 StaticSocketDataProvider ssl_bad_certificate(
3368 proxy_reads, arraysize(proxy_reads),
3369 proxy_writes, arraysize(proxy_writes));
3370 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3371 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593372 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3373 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333374
[email protected]5ecc992a42009-11-11 01:41:593375 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3376 session_deps.socket_factory.AddSocketDataProvider(&data);
3377 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3378 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333379
3380 TestCompletionCallback callback;
3381
3382 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593383 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333384
[email protected]d207a5f2009-06-04 05:28:403385 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433386 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333387
[email protected]5a1d7ca2010-04-28 20:12:273388 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333389 EXPECT_EQ(ERR_IO_PENDING, rv);
3390
3391 rv = callback.WaitForResult();
3392 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3393
3394 rv = trans->RestartIgnoringLastError(&callback);
3395 EXPECT_EQ(ERR_IO_PENDING, rv);
3396
3397 rv = callback.WaitForResult();
3398 EXPECT_EQ(OK, rv);
3399
3400 const HttpResponseInfo* response = trans->GetResponseInfo();
3401
3402 EXPECT_FALSE(response == NULL);
3403 EXPECT_EQ(100, response->headers->GetContentLength());
3404 }
3405}
3406
[email protected]1c773ea12009-04-28 19:58:423407TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593408 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403409 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433410 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423411
3412 HttpRequestInfo request;
3413 request.method = "GET";
3414 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433415 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3416 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423417
3418 MockWrite data_writes[] = {
3419 MockWrite("GET / HTTP/1.1\r\n"
3420 "Host: www.google.com\r\n"
3421 "Connection: keep-alive\r\n"
3422 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3423 };
3424
3425 // Lastly, the server responds with the actual content.
3426 MockRead data_reads[] = {
3427 MockRead("HTTP/1.0 200 OK\r\n"),
3428 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3429 MockRead("Content-Length: 100\r\n\r\n"),
3430 MockRead(false, OK),
3431 };
3432
[email protected]31a2bfe2010-02-09 08:03:393433 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3434 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593435 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423436
3437 TestCompletionCallback callback;
3438
[email protected]5a1d7ca2010-04-28 20:12:273439 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423440 EXPECT_EQ(ERR_IO_PENDING, rv);
3441
3442 rv = callback.WaitForResult();
3443 EXPECT_EQ(OK, rv);
3444}
3445
3446TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593447 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403448 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433449 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423450
3451 HttpRequestInfo request;
3452 request.method = "GET";
3453 request.url = GURL("http://www.google.com/");
3454 request.load_flags = 0;
3455 request.referrer = GURL("http://the.previous.site.com/");
3456
3457 MockWrite data_writes[] = {
3458 MockWrite("GET / HTTP/1.1\r\n"
3459 "Host: www.google.com\r\n"
3460 "Connection: keep-alive\r\n"
3461 "Referer: http://the.previous.site.com/\r\n\r\n"),
3462 };
3463
3464 // Lastly, the server responds with the actual content.
3465 MockRead data_reads[] = {
3466 MockRead("HTTP/1.0 200 OK\r\n"),
3467 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3468 MockRead("Content-Length: 100\r\n\r\n"),
3469 MockRead(false, OK),
3470 };
3471
[email protected]31a2bfe2010-02-09 08:03:393472 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3473 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593474 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423475
3476 TestCompletionCallback callback;
3477
[email protected]5a1d7ca2010-04-28 20:12:273478 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423479 EXPECT_EQ(ERR_IO_PENDING, rv);
3480
3481 rv = callback.WaitForResult();
3482 EXPECT_EQ(OK, rv);
3483}
3484
3485TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593486 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403487 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433488 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423489
3490 HttpRequestInfo request;
3491 request.method = "POST";
3492 request.url = GURL("http://www.google.com/");
3493
3494 MockWrite data_writes[] = {
3495 MockWrite("POST / HTTP/1.1\r\n"
3496 "Host: www.google.com\r\n"
3497 "Connection: keep-alive\r\n"
3498 "Content-Length: 0\r\n\r\n"),
3499 };
3500
3501 // Lastly, the server responds with the actual content.
3502 MockRead data_reads[] = {
3503 MockRead("HTTP/1.0 200 OK\r\n"),
3504 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3505 MockRead("Content-Length: 100\r\n\r\n"),
3506 MockRead(false, OK),
3507 };
3508
[email protected]31a2bfe2010-02-09 08:03:393509 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3510 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593511 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423512
3513 TestCompletionCallback callback;
3514
[email protected]5a1d7ca2010-04-28 20:12:273515 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423516 EXPECT_EQ(ERR_IO_PENDING, rv);
3517
3518 rv = callback.WaitForResult();
3519 EXPECT_EQ(OK, rv);
3520}
3521
3522TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593523 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403524 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433525 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423526
3527 HttpRequestInfo request;
3528 request.method = "PUT";
3529 request.url = GURL("http://www.google.com/");
3530
3531 MockWrite data_writes[] = {
3532 MockWrite("PUT / HTTP/1.1\r\n"
3533 "Host: www.google.com\r\n"
3534 "Connection: keep-alive\r\n"
3535 "Content-Length: 0\r\n\r\n"),
3536 };
3537
3538 // Lastly, the server responds with the actual content.
3539 MockRead data_reads[] = {
3540 MockRead("HTTP/1.0 200 OK\r\n"),
3541 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3542 MockRead("Content-Length: 100\r\n\r\n"),
3543 MockRead(false, OK),
3544 };
3545
[email protected]31a2bfe2010-02-09 08:03:393546 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3547 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593548 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423549
3550 TestCompletionCallback callback;
3551
[email protected]5a1d7ca2010-04-28 20:12:273552 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423553 EXPECT_EQ(ERR_IO_PENDING, rv);
3554
3555 rv = callback.WaitForResult();
3556 EXPECT_EQ(OK, rv);
3557}
3558
3559TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593560 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403561 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433562 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423563
3564 HttpRequestInfo request;
3565 request.method = "HEAD";
3566 request.url = GURL("http://www.google.com/");
3567
3568 MockWrite data_writes[] = {
3569 MockWrite("HEAD / HTTP/1.1\r\n"
3570 "Host: www.google.com\r\n"
3571 "Connection: keep-alive\r\n"
3572 "Content-Length: 0\r\n\r\n"),
3573 };
3574
3575 // Lastly, the server responds with the actual content.
3576 MockRead data_reads[] = {
3577 MockRead("HTTP/1.0 200 OK\r\n"),
3578 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3579 MockRead("Content-Length: 100\r\n\r\n"),
3580 MockRead(false, OK),
3581 };
3582
[email protected]31a2bfe2010-02-09 08:03:393583 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3584 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593585 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423586
3587 TestCompletionCallback callback;
3588
[email protected]5a1d7ca2010-04-28 20:12:273589 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423590 EXPECT_EQ(ERR_IO_PENDING, rv);
3591
3592 rv = callback.WaitForResult();
3593 EXPECT_EQ(OK, rv);
3594}
3595
3596TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593597 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403598 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433599 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423600
3601 HttpRequestInfo request;
3602 request.method = "GET";
3603 request.url = GURL("http://www.google.com/");
3604 request.load_flags = LOAD_BYPASS_CACHE;
3605
3606 MockWrite data_writes[] = {
3607 MockWrite("GET / HTTP/1.1\r\n"
3608 "Host: www.google.com\r\n"
3609 "Connection: keep-alive\r\n"
3610 "Pragma: no-cache\r\n"
3611 "Cache-Control: no-cache\r\n\r\n"),
3612 };
3613
3614 // Lastly, the server responds with the actual content.
3615 MockRead data_reads[] = {
3616 MockRead("HTTP/1.0 200 OK\r\n"),
3617 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3618 MockRead("Content-Length: 100\r\n\r\n"),
3619 MockRead(false, OK),
3620 };
3621
[email protected]31a2bfe2010-02-09 08:03:393622 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3623 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593624 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423625
3626 TestCompletionCallback callback;
3627
[email protected]5a1d7ca2010-04-28 20:12:273628 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423629 EXPECT_EQ(ERR_IO_PENDING, rv);
3630
3631 rv = callback.WaitForResult();
3632 EXPECT_EQ(OK, rv);
3633}
3634
3635TEST_F(HttpNetworkTransactionTest,
3636 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593637 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403638 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433639 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423640
3641 HttpRequestInfo request;
3642 request.method = "GET";
3643 request.url = GURL("http://www.google.com/");
3644 request.load_flags = LOAD_VALIDATE_CACHE;
3645
3646 MockWrite data_writes[] = {
3647 MockWrite("GET / HTTP/1.1\r\n"
3648 "Host: www.google.com\r\n"
3649 "Connection: keep-alive\r\n"
3650 "Cache-Control: max-age=0\r\n\r\n"),
3651 };
3652
3653 // Lastly, the server responds with the actual content.
3654 MockRead data_reads[] = {
3655 MockRead("HTTP/1.0 200 OK\r\n"),
3656 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3657 MockRead("Content-Length: 100\r\n\r\n"),
3658 MockRead(false, OK),
3659 };
3660
[email protected]31a2bfe2010-02-09 08:03:393661 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3662 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593663 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423664
3665 TestCompletionCallback callback;
3666
[email protected]5a1d7ca2010-04-28 20:12:273667 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423668 EXPECT_EQ(ERR_IO_PENDING, rv);
3669
3670 rv = callback.WaitForResult();
3671 EXPECT_EQ(OK, rv);
3672}
3673
3674TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593675 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403676 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433677 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423678
3679 HttpRequestInfo request;
3680 request.method = "GET";
3681 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433682 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423683
3684 MockWrite data_writes[] = {
3685 MockWrite("GET / HTTP/1.1\r\n"
3686 "Host: www.google.com\r\n"
3687 "Connection: keep-alive\r\n"
3688 "FooHeader: Bar\r\n\r\n"),
3689 };
3690
3691 // Lastly, the server responds with the actual content.
3692 MockRead data_reads[] = {
3693 MockRead("HTTP/1.0 200 OK\r\n"),
3694 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3695 MockRead("Content-Length: 100\r\n\r\n"),
3696 MockRead(false, OK),
3697 };
3698
[email protected]31a2bfe2010-02-09 08:03:393699 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3700 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593701 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423702
3703 TestCompletionCallback callback;
3704
[email protected]5a1d7ca2010-04-28 20:12:273705 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423706 EXPECT_EQ(ERR_IO_PENDING, rv);
3707
3708 rv = callback.WaitForResult();
3709 EXPECT_EQ(OK, rv);
3710}
3711
[email protected]270c6412010-03-29 22:02:473712TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3713 SessionDependencies session_deps;
3714 scoped_ptr<HttpTransaction> trans(
3715 new HttpNetworkTransaction(CreateSession(&session_deps)));
3716
3717 HttpRequestInfo request;
3718 request.method = "GET";
3719 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433720 request.extra_headers.SetHeader("referer", "www.foo.com");
3721 request.extra_headers.SetHeader("hEllo", "Kitty");
3722 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473723
3724 MockWrite data_writes[] = {
3725 MockWrite("GET / HTTP/1.1\r\n"
3726 "Host: www.google.com\r\n"
3727 "Connection: keep-alive\r\n"
3728 "hEllo: Kitty\r\n"
3729 "FoO: bar\r\n\r\n"),
3730 };
3731
3732 // Lastly, the server responds with the actual content.
3733 MockRead data_reads[] = {
3734 MockRead("HTTP/1.0 200 OK\r\n"),
3735 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3736 MockRead("Content-Length: 100\r\n\r\n"),
3737 MockRead(false, OK),
3738 };
3739
3740 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3741 data_writes, arraysize(data_writes));
3742 session_deps.socket_factory.AddSocketDataProvider(&data);
3743
3744 TestCompletionCallback callback;
3745
[email protected]5a1d7ca2010-04-28 20:12:273746 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473747 EXPECT_EQ(ERR_IO_PENDING, rv);
3748
3749 rv = callback.WaitForResult();
3750 EXPECT_EQ(OK, rv);
3751}
3752
[email protected]3cd17242009-06-23 02:59:023753TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093754 SessionDependencies session_deps(
3755 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023756
3757 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433758 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023759
3760 HttpRequestInfo request;
3761 request.method = "GET";
3762 request.url = GURL("http://www.google.com/");
3763 request.load_flags = 0;
3764
3765 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3766 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3767
3768 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353769 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023770 MockWrite("GET / HTTP/1.1\r\n"
3771 "Host: www.google.com\r\n"
3772 "Connection: keep-alive\r\n\r\n")
3773 };
3774
3775 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593776 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023777 MockRead("HTTP/1.0 200 OK\r\n"),
3778 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3779 MockRead("Payload"),
3780 MockRead(false, OK)
3781 };
3782
[email protected]31a2bfe2010-02-09 08:03:393783 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3784 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593785 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023786
3787 TestCompletionCallback callback;
3788
[email protected]5a1d7ca2010-04-28 20:12:273789 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023790 EXPECT_EQ(ERR_IO_PENDING, rv);
3791
3792 rv = callback.WaitForResult();
3793 EXPECT_EQ(OK, rv);
3794
3795 const HttpResponseInfo* response = trans->GetResponseInfo();
3796 EXPECT_FALSE(response == NULL);
3797
3798 std::string response_text;
3799 rv = ReadTransaction(trans.get(), &response_text);
3800 EXPECT_EQ(OK, rv);
3801 EXPECT_EQ("Payload", response_text);
3802}
3803
3804TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093805 SessionDependencies session_deps(
3806 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023807
3808 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433809 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023810
3811 HttpRequestInfo request;
3812 request.method = "GET";
3813 request.url = GURL("https://www.google.com/");
3814 request.load_flags = 0;
3815
3816 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3817 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3818
3819 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353820 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3821 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023822 MockWrite("GET / HTTP/1.1\r\n"
3823 "Host: www.google.com\r\n"
3824 "Connection: keep-alive\r\n\r\n")
3825 };
3826
3827 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353828 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3829 arraysize(read_buffer)),
3830 MockRead("HTTP/1.0 200 OK\r\n"),
3831 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3832 MockRead("Payload"),
3833 MockRead(false, OK)
3834 };
3835
[email protected]31a2bfe2010-02-09 08:03:393836 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3837 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593838 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353839
[email protected]5ecc992a42009-11-11 01:41:593840 SSLSocketDataProvider ssl(true, OK);
3841 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353842
3843 TestCompletionCallback callback;
3844
[email protected]5a1d7ca2010-04-28 20:12:273845 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353846 EXPECT_EQ(ERR_IO_PENDING, rv);
3847
3848 rv = callback.WaitForResult();
3849 EXPECT_EQ(OK, rv);
3850
3851 const HttpResponseInfo* response = trans->GetResponseInfo();
3852 EXPECT_FALSE(response == NULL);
3853
3854 std::string response_text;
3855 rv = ReadTransaction(trans.get(), &response_text);
3856 EXPECT_EQ(OK, rv);
3857 EXPECT_EQ("Payload", response_text);
3858}
3859
3860TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093861 SessionDependencies session_deps(
3862 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353863
3864 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433865 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353866
3867 HttpRequestInfo request;
3868 request.method = "GET";
3869 request.url = GURL("http://www.google.com/");
3870 request.load_flags = 0;
3871
3872 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3873 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373874 const char kSOCKS5OkRequest[] = {
3875 0x05, // Version
3876 0x01, // Command (CONNECT)
3877 0x00, // Reserved.
3878 0x03, // Address type (DOMAINNAME).
3879 0x0E, // Length of domain (14)
3880 // Domain string:
3881 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3882 0x00, 0x50, // 16-bit port (80)
3883 };
[email protected]e0c27be2009-07-15 13:09:353884 const char kSOCKS5OkResponse[] =
3885 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3886
3887 MockWrite data_writes[] = {
3888 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3889 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3890 MockWrite("GET / HTTP/1.1\r\n"
3891 "Host: www.google.com\r\n"
3892 "Connection: keep-alive\r\n\r\n")
3893 };
3894
3895 MockRead data_reads[] = {
3896 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3897 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3898 MockRead("HTTP/1.0 200 OK\r\n"),
3899 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3900 MockRead("Payload"),
3901 MockRead(false, OK)
3902 };
3903
[email protected]31a2bfe2010-02-09 08:03:393904 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3905 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593906 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353907
3908 TestCompletionCallback callback;
3909
[email protected]5a1d7ca2010-04-28 20:12:273910 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353911 EXPECT_EQ(ERR_IO_PENDING, rv);
3912
3913 rv = callback.WaitForResult();
3914 EXPECT_EQ(OK, rv);
3915
3916 const HttpResponseInfo* response = trans->GetResponseInfo();
3917 EXPECT_FALSE(response == NULL);
3918
3919 std::string response_text;
3920 rv = ReadTransaction(trans.get(), &response_text);
3921 EXPECT_EQ(OK, rv);
3922 EXPECT_EQ("Payload", response_text);
3923}
3924
3925TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093926 SessionDependencies session_deps(
3927 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353928
3929 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433930 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353931
3932 HttpRequestInfo request;
3933 request.method = "GET";
3934 request.url = GURL("https://www.google.com/");
3935 request.load_flags = 0;
3936
3937 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3938 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373939 const unsigned char kSOCKS5OkRequest[] = {
3940 0x05, // Version
3941 0x01, // Command (CONNECT)
3942 0x00, // Reserved.
3943 0x03, // Address type (DOMAINNAME).
3944 0x0E, // Length of domain (14)
3945 // Domain string:
3946 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3947 0x01, 0xBB, // 16-bit port (443)
3948 };
3949
[email protected]e0c27be2009-07-15 13:09:353950 const char kSOCKS5OkResponse[] =
3951 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3952
3953 MockWrite data_writes[] = {
3954 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3955 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3956 arraysize(kSOCKS5OkRequest)),
3957 MockWrite("GET / HTTP/1.1\r\n"
3958 "Host: www.google.com\r\n"
3959 "Connection: keep-alive\r\n\r\n")
3960 };
3961
3962 MockRead data_reads[] = {
3963 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3964 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023965 MockRead("HTTP/1.0 200 OK\r\n"),
3966 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3967 MockRead("Payload"),
3968 MockRead(false, OK)
3969 };
3970
[email protected]31a2bfe2010-02-09 08:03:393971 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3972 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593973 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023974
[email protected]5ecc992a42009-11-11 01:41:593975 SSLSocketDataProvider ssl(true, OK);
3976 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023977
3978 TestCompletionCallback callback;
3979
[email protected]5a1d7ca2010-04-28 20:12:273980 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023981 EXPECT_EQ(ERR_IO_PENDING, rv);
3982
3983 rv = callback.WaitForResult();
3984 EXPECT_EQ(OK, rv);
3985
3986 const HttpResponseInfo* response = trans->GetResponseInfo();
3987 EXPECT_FALSE(response == NULL);
3988
3989 std::string response_text;
3990 rv = ReadTransaction(trans.get(), &response_text);
3991 EXPECT_EQ(OK, rv);
3992 EXPECT_EQ("Payload", response_text);
3993}
3994
[email protected]04e5be32009-06-26 20:00:313995// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:063996
3997struct GroupNameTest {
3998 std::string proxy_server;
3999 std::string url;
4000 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:184001 bool ssl;
[email protected]2d731a32010-04-29 01:04:064002};
4003
4004scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
4005 const std::string& proxy_server) {
4006 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
4007 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4008
4009 HttpAlternateProtocols* alternate_protocols =
4010 session->mutable_alternate_protocols();
4011 alternate_protocols->SetAlternateProtocolFor(
4012 HostPortPair("host.with.alternate", 80), 443,
4013 HttpAlternateProtocols::NPN_SPDY_1);
4014
4015 return session;
4016}
4017
4018int GroupNameTransactionHelper(
4019 const std::string& url,
4020 const scoped_refptr<HttpNetworkSession>& session) {
4021 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4022
4023 HttpRequestInfo request;
4024 request.method = "GET";
4025 request.url = GURL(url);
4026 request.load_flags = 0;
4027
4028 TestCompletionCallback callback;
4029
4030 // We do not complete this request, the dtor will clean the transaction up.
4031 return trans->Start(&request, &callback, BoundNetLog());
4032}
4033
4034TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
4035 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:314036 {
[email protected]2d731a32010-04-29 01:04:064037 "", // unused
[email protected]04e5be32009-06-26 20:00:314038 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544039 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184040 false,
[email protected]2ff8b312010-04-26 22:20:544041 },
4042 {
[email protected]2d731a32010-04-29 01:04:064043 "", // unused
[email protected]2ff8b312010-04-26 22:20:544044 "http://[2001:1418:13:1::25]/direct",
4045 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:184046 false,
[email protected]04e5be32009-06-26 20:00:314047 },
[email protected]04e5be32009-06-26 20:00:314048
4049 // SSL Tests
4050 {
[email protected]2d731a32010-04-29 01:04:064051 "", // unused
[email protected]04e5be32009-06-26 20:00:314052 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024053 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184054 true,
[email protected]04e5be32009-06-26 20:00:314055 },
4056 {
[email protected]2d731a32010-04-29 01:04:064057 "", // unused
4058 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024059 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:184060 true,
[email protected]04e5be32009-06-26 20:00:314061 },
4062 {
[email protected]2d731a32010-04-29 01:04:064063 "", // unused
[email protected]2ff8b312010-04-26 22:20:544064 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024065 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184066 true,
[email protected]2ff8b312010-04-26 22:20:544067 },
[email protected]2d731a32010-04-29 01:04:064068 };
[email protected]2ff8b312010-04-26 22:20:544069
[email protected]2d731a32010-04-29 01:04:064070 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4071
4072 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4073 scoped_refptr<HttpNetworkSession> session(
4074 SetupSessionForGroupNameTests(tests[i].proxy_server));
4075
4076 HttpNetworkSessionPeer peer(session);
4077 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
4078 new CaptureGroupNameTCPSocketPool(session.get()));
4079 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]e60e47a2010-07-14 03:37:184080 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4081 new CaptureGroupNameSSLSocketPool(session.get()));
4082 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064083
4084 EXPECT_EQ(ERR_IO_PENDING,
4085 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184086 if (tests[i].ssl)
4087 EXPECT_EQ(tests[i].expected_group_name,
4088 ssl_conn_pool->last_group_name_received());
4089 else
4090 EXPECT_EQ(tests[i].expected_group_name,
4091 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064092 }
4093
4094 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4095}
4096
4097TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
4098 const GroupNameTest tests[] = {
4099 {
4100 "http_proxy",
4101 "http://www.google.com/http_proxy_normal",
4102 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184103 false,
[email protected]2d731a32010-04-29 01:04:064104 },
4105
4106 // SSL Tests
4107 {
4108 "http_proxy",
4109 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024110 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184111 true,
[email protected]2d731a32010-04-29 01:04:064112 },
4113
[email protected]9faeded92010-04-29 20:03:054114 {
4115 "http_proxy",
4116 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024117 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184118 true,
[email protected]9faeded92010-04-29 20:03:054119 },
[email protected]2d731a32010-04-29 01:04:064120 };
4121
4122 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4123
4124 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4125 scoped_refptr<HttpNetworkSession> session(
4126 SetupSessionForGroupNameTests(tests[i].proxy_server));
4127
4128 HttpNetworkSessionPeer peer(session);
4129
[email protected]e60e47a2010-07-14 03:37:184130 HostPortPair proxy_host("http_proxy", 80);
[email protected]e772db3f2010-07-12 18:11:134131 scoped_refptr<CaptureGroupNameHttpProxySocketPool> http_proxy_pool(
4132 new CaptureGroupNameHttpProxySocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184133 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
4134 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4135 new CaptureGroupNameSSLSocketPool(session.get()));
4136 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064137
4138 EXPECT_EQ(ERR_IO_PENDING,
4139 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184140 if (tests[i].ssl)
4141 EXPECT_EQ(tests[i].expected_group_name,
4142 ssl_conn_pool->last_group_name_received());
4143 else
4144 EXPECT_EQ(tests[i].expected_group_name,
4145 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064146 }
4147
4148 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4149}
4150
4151TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4152 const GroupNameTest tests[] = {
4153 {
4154 "socks4://socks_proxy:1080",
4155 "http://www.google.com/socks4_direct",
4156 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184157 false,
[email protected]2d731a32010-04-29 01:04:064158 },
4159 {
4160 "socks5://socks_proxy:1080",
4161 "http://www.google.com/socks5_direct",
4162 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184163 false,
[email protected]2d731a32010-04-29 01:04:064164 },
4165
4166 // SSL Tests
4167 {
4168 "socks4://socks_proxy:1080",
4169 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024170 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184171 true,
[email protected]2d731a32010-04-29 01:04:064172 },
4173 {
4174 "socks5://socks_proxy:1080",
4175 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024176 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184177 true,
[email protected]2d731a32010-04-29 01:04:064178 },
4179
[email protected]9faeded92010-04-29 20:03:054180 {
4181 "socks4://socks_proxy:1080",
4182 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024183 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184184 true,
[email protected]9faeded92010-04-29 20:03:054185 },
[email protected]04e5be32009-06-26 20:00:314186 };
4187
[email protected]2ff8b312010-04-26 22:20:544188 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4189
[email protected]04e5be32009-06-26 20:00:314190 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064191 scoped_refptr<HttpNetworkSession> session(
4192 SetupSessionForGroupNameTests(tests[i].proxy_server));
4193 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314194
[email protected]e60e47a2010-07-14 03:37:184195 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]a796bcec2010-03-22 17:17:264196 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064197 new CaptureGroupNameSOCKSSocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184198 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
4199 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4200 new CaptureGroupNameSSLSocketPool(session.get()));
4201 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:314202
[email protected]5695b8c2009-09-30 21:36:434203 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314204
[email protected]2d731a32010-04-29 01:04:064205 EXPECT_EQ(ERR_IO_PENDING,
4206 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184207 if (tests[i].ssl)
4208 EXPECT_EQ(tests[i].expected_group_name,
4209 ssl_conn_pool->last_group_name_received());
4210 else
4211 EXPECT_EQ(tests[i].expected_group_name,
4212 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314213 }
[email protected]2ff8b312010-04-26 22:20:544214
4215 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:314216}
4217
[email protected]9172a982009-06-06 00:30:254218TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544219 SessionDependencies session_deps(
4220 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324221
[email protected]69719062010-01-05 20:09:214222 // This simulates failure resolving all hostnames; that means we will fail
4223 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324224 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4225
[email protected]9172a982009-06-06 00:30:254226 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434227 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254228
4229 HttpRequestInfo request;
4230 request.method = "GET";
4231 request.url = GURL("http://www.google.com/");
4232
4233 TestCompletionCallback callback;
4234
[email protected]5a1d7ca2010-04-28 20:12:274235 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254236 EXPECT_EQ(ERR_IO_PENDING, rv);
4237
[email protected]9172a982009-06-06 00:30:254238 rv = callback.WaitForResult();
4239 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4240}
4241
[email protected]f3e6c1e2009-06-15 20:52:124242// Host resolution observer used by
4243// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4244// resovle requests are issued with a referrer of |expected_referrer|.
4245class ResolutionReferrerObserver : public HostResolver::Observer {
4246 public:
4247 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4248 : expected_referrer_(expected_referrer),
4249 called_start_with_referrer_(false),
4250 called_finish_with_referrer_(false) {
4251 }
4252
4253 virtual void OnStartResolution(int id,
4254 const HostResolver::RequestInfo& info) {
4255 if (info.referrer() == expected_referrer_)
4256 called_start_with_referrer_ = true;
4257 }
4258
4259 virtual void OnFinishResolutionWithStatus(
4260 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4261 if (info.referrer() == expected_referrer_)
4262 called_finish_with_referrer_ = true;
4263 }
4264
[email protected]eb255d32009-06-17 02:11:034265 virtual void OnCancelResolution(int id,
4266 const HostResolver::RequestInfo& info ) {
4267 FAIL() << "Should not be cancelling any requests!";
4268 }
4269
[email protected]f3e6c1e2009-06-15 20:52:124270 bool did_complete_with_expected_referrer() const {
4271 return called_start_with_referrer_ && called_finish_with_referrer_;
4272 }
4273
4274 private:
4275 GURL expected_referrer_;
4276 bool called_start_with_referrer_;
4277 bool called_finish_with_referrer_;
4278
4279 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4280};
4281
4282// Make sure that when HostResolver::Resolve() is invoked, it passes through
4283// the "referrer". This is depended on by the DNS prefetch observer.
4284TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4285 GURL referrer = GURL("http://expected-referrer/");
4286 EXPECT_TRUE(referrer.is_valid());
4287 ResolutionReferrerObserver resolution_observer(referrer);
4288
4289 SessionDependencies session_deps;
4290 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434291 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124292
4293 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144294 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124295
4296 // Connect up a mock socket which will fail when reading.
4297 MockRead data_reads[] = {
4298 MockRead(false, ERR_FAILED),
4299 };
[email protected]31a2bfe2010-02-09 08:03:394300 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594301 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124302
4303 // Issue a request, containing an HTTP referrer.
4304 HttpRequestInfo request;
4305 request.method = "GET";
4306 request.referrer = referrer;
4307 request.url = GURL("http://www.google.com/");
4308
4309 // Run the request until it fails reading from the socket.
4310 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274311 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124312 EXPECT_EQ(ERR_IO_PENDING, rv);
4313 rv = callback.WaitForResult();
4314 EXPECT_EQ(ERR_FAILED, rv);
4315
4316 // Check that the host resolution observer saw |referrer|.
4317 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4318}
4319
[email protected]685af592010-05-11 19:31:244320// Base test to make sure that when the load flags for a request specify to
4321// bypass the cache, the DNS cache is not used.
4322void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284323 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324324
[email protected]a2c2fb92009-07-18 07:31:044325 // Select a host resolver that does caching.
4326 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324327
[email protected]3b9cca42009-06-16 01:08:284328 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434329 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284330
4331 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4332 // a synchronous lookup.)
4333 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144334 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464335 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274336 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284337 EXPECT_EQ(OK, rv);
4338
4339 // Verify that it was added to host cache, by doing a subsequent async lookup
4340 // and confirming it completes synchronously.
4341 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464342 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284343 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274344 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324345 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284346
4347 // Inject a failure the next time that "www.google.com" is resolved. This way
4348 // we can tell if the next lookup hit the cache, or the "network".
4349 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324350 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284351
4352 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4353 // first read -- this won't be reached as the host resolution will fail first.
4354 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394355 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594356 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284357
4358 // Issue a request, asking to bypass the cache(s).
4359 HttpRequestInfo request;
4360 request.method = "GET";
[email protected]685af592010-05-11 19:31:244361 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284362 request.url = GURL("http://www.google.com/");
4363
4364 // Run the request.
4365 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274366 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284367 ASSERT_EQ(ERR_IO_PENDING, rv);
4368 rv = callback.WaitForResult();
4369
4370 // If we bypassed the cache, we would have gotten a failure while resolving
4371 // "www.google.com".
4372 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4373}
4374
[email protected]685af592010-05-11 19:31:244375// There are multiple load flags that should trigger the host cache bypass.
4376// Test each in isolation:
4377TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4378 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4379}
4380
4381TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4382 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4383}
4384
4385TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
4386 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
4387}
4388
[email protected]0877e3d2009-10-17 22:29:574389// Make sure we can handle an error when writing the request.
4390TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4391 SessionDependencies session_deps;
4392 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4393
4394 HttpRequestInfo request;
4395 request.method = "GET";
4396 request.url = GURL("http://www.foo.com/");
4397 request.load_flags = 0;
4398
4399 MockWrite write_failure[] = {
4400 MockWrite(true, ERR_CONNECTION_RESET),
4401 };
[email protected]31a2bfe2010-02-09 08:03:394402 StaticSocketDataProvider data(NULL, 0,
4403 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594404 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574405
4406 TestCompletionCallback callback;
4407
4408 scoped_ptr<HttpTransaction> trans(
4409 new HttpNetworkTransaction(CreateSession(&session_deps)));
4410
[email protected]5a1d7ca2010-04-28 20:12:274411 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574412 EXPECT_EQ(ERR_IO_PENDING, rv);
4413
4414 rv = callback.WaitForResult();
4415 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4416}
4417
4418// Check that a connection closed after the start of the headers finishes ok.
4419TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4420 SessionDependencies session_deps;
4421 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4422
4423 HttpRequestInfo request;
4424 request.method = "GET";
4425 request.url = GURL("http://www.foo.com/");
4426 request.load_flags = 0;
4427
4428 MockRead data_reads[] = {
4429 MockRead("HTTP/1."),
4430 MockRead(false, OK),
4431 };
4432
[email protected]31a2bfe2010-02-09 08:03:394433 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594434 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574435
4436 TestCompletionCallback callback;
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(OK, rv);
4446
4447 const HttpResponseInfo* response = trans->GetResponseInfo();
4448 EXPECT_TRUE(response != NULL);
4449
4450 EXPECT_TRUE(response->headers != NULL);
4451 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4452
4453 std::string response_data;
4454 rv = ReadTransaction(trans.get(), &response_data);
4455 EXPECT_EQ(OK, rv);
4456 EXPECT_EQ("", response_data);
4457}
4458
4459// Make sure that a dropped connection while draining the body for auth
4460// restart does the right thing.
4461TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4462 SessionDependencies session_deps;
4463 scoped_ptr<HttpTransaction> trans(
4464 new HttpNetworkTransaction(CreateSession(&session_deps)));
4465
4466 HttpRequestInfo request;
4467 request.method = "GET";
4468 request.url = GURL("http://www.google.com/");
4469 request.load_flags = 0;
4470
4471 MockWrite data_writes1[] = {
4472 MockWrite("GET / HTTP/1.1\r\n"
4473 "Host: www.google.com\r\n"
4474 "Connection: keep-alive\r\n\r\n"),
4475 };
4476
4477 MockRead data_reads1[] = {
4478 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4479 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4480 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4481 MockRead("Content-Length: 14\r\n\r\n"),
4482 MockRead("Unauth"),
4483 MockRead(true, ERR_CONNECTION_RESET),
4484 };
4485
[email protected]31a2bfe2010-02-09 08:03:394486 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4487 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594488 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574489
4490 // After calling trans->RestartWithAuth(), this is the request we should
4491 // be issuing -- the final header line contains the credentials.
4492 MockWrite data_writes2[] = {
4493 MockWrite("GET / HTTP/1.1\r\n"
4494 "Host: www.google.com\r\n"
4495 "Connection: keep-alive\r\n"
4496 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4497 };
4498
4499 // Lastly, the server responds with the actual content.
4500 MockRead data_reads2[] = {
4501 MockRead("HTTP/1.1 200 OK\r\n"),
4502 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4503 MockRead("Content-Length: 100\r\n\r\n"),
4504 MockRead(false, OK),
4505 };
4506
[email protected]31a2bfe2010-02-09 08:03:394507 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4508 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594509 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574510
4511 TestCompletionCallback callback1;
4512
[email protected]5a1d7ca2010-04-28 20:12:274513 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574514 EXPECT_EQ(ERR_IO_PENDING, rv);
4515
4516 rv = callback1.WaitForResult();
4517 EXPECT_EQ(OK, rv);
4518
4519 const HttpResponseInfo* response = trans->GetResponseInfo();
4520 EXPECT_FALSE(response == NULL);
4521
4522 // The password prompt info should have been set in response->auth_challenge.
4523 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4524
4525 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4526 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4527 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4528
4529 TestCompletionCallback callback2;
4530
4531 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4532 EXPECT_EQ(ERR_IO_PENDING, rv);
4533
4534 rv = callback2.WaitForResult();
4535 EXPECT_EQ(OK, rv);
4536
4537 response = trans->GetResponseInfo();
4538 EXPECT_FALSE(response == NULL);
4539 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4540 EXPECT_EQ(100, response->headers->GetContentLength());
4541}
4542
4543// Test HTTPS connections going through a proxy that sends extra data.
4544TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4545 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4546
4547 HttpRequestInfo request;
4548 request.method = "GET";
4549 request.url = GURL("https://www.google.com/");
4550 request.load_flags = 0;
4551
4552 MockRead proxy_reads[] = {
4553 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4554 MockRead(false, OK)
4555 };
4556
[email protected]31a2bfe2010-02-09 08:03:394557 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594558 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574559
[email protected]5ecc992a42009-11-11 01:41:594560 session_deps.socket_factory.AddSocketDataProvider(&data);
4561 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574562
4563 TestCompletionCallback callback;
4564
4565 session_deps.socket_factory.ResetNextMockIndexes();
4566
4567 scoped_ptr<HttpTransaction> trans(
4568 new HttpNetworkTransaction(CreateSession(&session_deps)));
4569
[email protected]5a1d7ca2010-04-28 20:12:274570 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574571 EXPECT_EQ(ERR_IO_PENDING, rv);
4572
4573 rv = callback.WaitForResult();
4574 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4575}
4576
[email protected]e22e1362009-11-23 21:31:124577TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464578 SessionDependencies session_deps;
4579 scoped_ptr<HttpTransaction> trans(
4580 new HttpNetworkTransaction(CreateSession(&session_deps)));
4581
4582 HttpRequestInfo request;
4583 request.method = "GET";
4584 request.url = GURL("http://www.google.com/");
4585 request.load_flags = 0;
4586
[email protected]e22e1362009-11-23 21:31:124587 MockRead data_reads[] = {
4588 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4589 MockRead(false, OK),
4590 };
[email protected]9492e4a2010-02-24 00:58:464591
4592 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4593 session_deps.socket_factory.AddSocketDataProvider(&data);
4594
4595 TestCompletionCallback callback;
4596
[email protected]5a1d7ca2010-04-28 20:12:274597 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464598 EXPECT_EQ(ERR_IO_PENDING, rv);
4599
4600 EXPECT_EQ(OK, callback.WaitForResult());
4601
4602 const HttpResponseInfo* response = trans->GetResponseInfo();
4603 EXPECT_TRUE(response != NULL);
4604
4605 EXPECT_TRUE(response->headers != NULL);
4606 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4607
4608 std::string response_data;
4609 rv = ReadTransaction(trans.get(), &response_data);
4610 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124611}
4612
[email protected]95d88ffe2010-02-04 21:25:334613TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4614 SessionDependencies session_deps;
4615 scoped_ptr<HttpTransaction> trans(
4616 new HttpNetworkTransaction(CreateSession(&session_deps)));
4617
4618 HttpRequestInfo request;
4619 request.method = "POST";
4620 request.url = GURL("http://www.google.com/upload");
4621 request.upload_data = new UploadData;
4622 request.load_flags = 0;
4623
4624 FilePath temp_file_path;
4625 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4626 const uint64 kFakeSize = 100000; // file is actually blank
4627
4628 std::vector<UploadData::Element> elements;
4629 UploadData::Element element;
4630 element.SetToFilePath(temp_file_path);
4631 element.SetContentLength(kFakeSize);
4632 elements.push_back(element);
4633 request.upload_data->set_elements(elements);
4634 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4635
4636 MockRead data_reads[] = {
4637 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4638 MockRead("hello world"),
4639 MockRead(false, OK),
4640 };
[email protected]31a2bfe2010-02-09 08:03:394641 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334642 session_deps.socket_factory.AddSocketDataProvider(&data);
4643
4644 TestCompletionCallback callback;
4645
[email protected]5a1d7ca2010-04-28 20:12:274646 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334647 EXPECT_EQ(ERR_IO_PENDING, rv);
4648
4649 rv = callback.WaitForResult();
4650 EXPECT_EQ(OK, rv);
4651
4652 const HttpResponseInfo* response = trans->GetResponseInfo();
4653 EXPECT_TRUE(response != NULL);
4654
4655 EXPECT_TRUE(response->headers != NULL);
4656 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4657
4658 std::string response_data;
4659 rv = ReadTransaction(trans.get(), &response_data);
4660 EXPECT_EQ(OK, rv);
4661 EXPECT_EQ("hello world", response_data);
4662
4663 file_util::Delete(temp_file_path, false);
4664}
4665
[email protected]6624b4622010-03-29 19:58:364666TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4667 // If we try to upload an unreadable file, the network stack should report
4668 // the file size as zero and upload zero bytes for that file.
4669 SessionDependencies session_deps;
4670 scoped_ptr<HttpTransaction> trans(
4671 new HttpNetworkTransaction(CreateSession(&session_deps)));
4672
4673 FilePath temp_file;
4674 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4675 std::string temp_file_content("Unreadable file.");
4676 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4677 temp_file_content.length()));
4678 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4679
4680 HttpRequestInfo request;
4681 request.method = "POST";
4682 request.url = GURL("http://www.google.com/upload");
4683 request.upload_data = new UploadData;
4684 request.load_flags = 0;
4685
4686 std::vector<UploadData::Element> elements;
4687 UploadData::Element element;
4688 element.SetToFilePath(temp_file);
4689 elements.push_back(element);
4690 request.upload_data->set_elements(elements);
4691
4692 MockRead data_reads[] = {
4693 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4694 MockRead(false, OK),
4695 };
4696 MockWrite data_writes[] = {
4697 MockWrite("POST /upload HTTP/1.1\r\n"
4698 "Host: www.google.com\r\n"
4699 "Connection: keep-alive\r\n"
4700 "Content-Length: 0\r\n\r\n"),
4701 MockWrite(false, OK),
4702 };
4703 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4704 arraysize(data_writes));
4705 session_deps.socket_factory.AddSocketDataProvider(&data);
4706
4707 TestCompletionCallback callback;
4708
[email protected]5a1d7ca2010-04-28 20:12:274709 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364710 EXPECT_EQ(ERR_IO_PENDING, rv);
4711
4712 rv = callback.WaitForResult();
4713 EXPECT_EQ(OK, rv);
4714
4715 const HttpResponseInfo* response = trans->GetResponseInfo();
4716 EXPECT_TRUE(response != NULL);
4717 EXPECT_TRUE(response->headers != NULL);
4718 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4719
4720 file_util::Delete(temp_file, false);
4721}
4722
4723TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4724 SessionDependencies session_deps;
4725 scoped_ptr<HttpTransaction> trans(
4726 new HttpNetworkTransaction(CreateSession(&session_deps)));
4727
4728 FilePath temp_file;
4729 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4730 std::string temp_file_contents("Unreadable file.");
4731 std::string unreadable_contents(temp_file_contents.length(), '\0');
4732 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4733 temp_file_contents.length()));
4734
4735 HttpRequestInfo request;
4736 request.method = "POST";
4737 request.url = GURL("http://www.google.com/upload");
4738 request.upload_data = new UploadData;
4739 request.load_flags = 0;
4740
4741 std::vector<UploadData::Element> elements;
4742 UploadData::Element element;
4743 element.SetToFilePath(temp_file);
4744 elements.push_back(element);
4745 request.upload_data->set_elements(elements);
4746
4747 MockRead data_reads[] = {
4748 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4749 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4750 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4751
4752 MockRead("HTTP/1.1 200 OK\r\n"),
4753 MockRead("Content-Length: 0\r\n\r\n"),
4754 MockRead(false, OK),
4755 };
4756 MockWrite data_writes[] = {
4757 MockWrite("POST /upload HTTP/1.1\r\n"
4758 "Host: www.google.com\r\n"
4759 "Connection: keep-alive\r\n"
4760 "Content-Length: 16\r\n\r\n"),
4761 MockWrite(false, temp_file_contents.c_str()),
4762
4763 MockWrite("POST /upload HTTP/1.1\r\n"
4764 "Host: www.google.com\r\n"
4765 "Connection: keep-alive\r\n"
4766 "Content-Length: 16\r\n"
4767 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4768 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4769 MockWrite(false, OK),
4770 };
4771 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4772 arraysize(data_writes));
4773 session_deps.socket_factory.AddSocketDataProvider(&data);
4774
4775 TestCompletionCallback callback1;
4776
[email protected]5a1d7ca2010-04-28 20:12:274777 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364778 EXPECT_EQ(ERR_IO_PENDING, rv);
4779
4780 rv = callback1.WaitForResult();
4781 EXPECT_EQ(OK, rv);
4782
4783 const HttpResponseInfo* response = trans->GetResponseInfo();
4784 EXPECT_TRUE(response != NULL);
4785 EXPECT_TRUE(response->headers != NULL);
4786 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4787
4788 // The password prompt info should have been set in response->auth_challenge.
4789 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4790 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4791 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4792 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4793
4794 // Now make the file unreadable and try again.
4795 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4796
4797 TestCompletionCallback callback2;
4798
4799 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4800 EXPECT_EQ(ERR_IO_PENDING, rv);
4801
4802 rv = callback2.WaitForResult();
4803 EXPECT_EQ(OK, rv);
4804
4805 response = trans->GetResponseInfo();
4806 EXPECT_TRUE(response != NULL);
4807 EXPECT_TRUE(response->headers != NULL);
4808 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4809 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4810
4811 file_util::Delete(temp_file, false);
4812}
4813
[email protected]aeefc9e82010-02-19 16:18:274814// Tests that changes to Auth realms are treated like auth rejections.
4815TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4816 SessionDependencies session_deps;
4817 scoped_ptr<HttpTransaction> trans(
4818 new HttpNetworkTransaction(CreateSession(&session_deps)));
4819
4820 HttpRequestInfo request;
4821 request.method = "GET";
4822 request.url = GURL("http://www.google.com/");
4823 request.load_flags = 0;
4824
4825 // First transaction will request a resource and receive a Basic challenge
4826 // with realm="first_realm".
4827 MockWrite data_writes1[] = {
4828 MockWrite("GET / HTTP/1.1\r\n"
4829 "Host: www.google.com\r\n"
4830 "Connection: keep-alive\r\n"
4831 "\r\n"),
4832 };
4833 MockRead data_reads1[] = {
4834 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4835 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4836 "\r\n"),
4837 };
4838
4839 // After calling trans->RestartWithAuth(), provide an Authentication header
4840 // for first_realm. The server will reject and provide a challenge with
4841 // second_realm.
4842 MockWrite data_writes2[] = {
4843 MockWrite("GET / HTTP/1.1\r\n"
4844 "Host: www.google.com\r\n"
4845 "Connection: keep-alive\r\n"
4846 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4847 "\r\n"),
4848 };
4849 MockRead data_reads2[] = {
4850 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4851 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4852 "\r\n"),
4853 };
4854
4855 // This again fails, and goes back to first_realm. Make sure that the
4856 // entry is removed from cache.
4857 MockWrite data_writes3[] = {
4858 MockWrite("GET / HTTP/1.1\r\n"
4859 "Host: www.google.com\r\n"
4860 "Connection: keep-alive\r\n"
4861 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4862 "\r\n"),
4863 };
4864 MockRead data_reads3[] = {
4865 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4866 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4867 "\r\n"),
4868 };
4869
4870 // Try one last time (with the correct password) and get the resource.
4871 MockWrite data_writes4[] = {
4872 MockWrite("GET / HTTP/1.1\r\n"
4873 "Host: www.google.com\r\n"
4874 "Connection: keep-alive\r\n"
4875 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4876 "\r\n"),
4877 };
4878 MockRead data_reads4[] = {
4879 MockRead("HTTP/1.1 200 OK\r\n"
4880 "Content-Type: text/html; charset=iso-8859-1\r\n"
4881 "Content-Length: 100\r\n"
4882 "\r\n"),
4883 };
4884
4885 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4886 data_writes1, arraysize(data_writes1));
4887 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4888 data_writes2, arraysize(data_writes2));
4889 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4890 data_writes3, arraysize(data_writes3));
4891 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4892 data_writes4, arraysize(data_writes4));
4893 session_deps.socket_factory.AddSocketDataProvider(&data1);
4894 session_deps.socket_factory.AddSocketDataProvider(&data2);
4895 session_deps.socket_factory.AddSocketDataProvider(&data3);
4896 session_deps.socket_factory.AddSocketDataProvider(&data4);
4897
4898 TestCompletionCallback callback1;
4899
4900 // Issue the first request with Authorize headers. There should be a
4901 // password prompt for first_realm waiting to be filled in after the
4902 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:274903 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:274904 EXPECT_EQ(ERR_IO_PENDING, rv);
4905 rv = callback1.WaitForResult();
4906 EXPECT_EQ(OK, rv);
4907 const HttpResponseInfo* response = trans->GetResponseInfo();
4908 ASSERT_FALSE(response == NULL);
4909 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4910 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4911 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4912 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4913
4914 // Issue the second request with an incorrect password. There should be a
4915 // password prompt for second_realm waiting to be filled in after the
4916 // transaction completes.
4917 TestCompletionCallback callback2;
4918 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4919 EXPECT_EQ(ERR_IO_PENDING, rv);
4920 rv = callback2.WaitForResult();
4921 EXPECT_EQ(OK, rv);
4922 response = trans->GetResponseInfo();
4923 ASSERT_FALSE(response == NULL);
4924 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4925 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4926 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4927 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4928
4929 // Issue the third request with another incorrect password. There should be
4930 // a password prompt for first_realm waiting to be filled in. If the password
4931 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4932 // first_realm was not correctly removed.
4933 TestCompletionCallback callback3;
4934 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4935 EXPECT_EQ(ERR_IO_PENDING, rv);
4936 rv = callback3.WaitForResult();
4937 EXPECT_EQ(OK, rv);
4938 response = trans->GetResponseInfo();
4939 ASSERT_FALSE(response == NULL);
4940 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4941 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4942 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4943 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4944
4945 // Issue the fourth request with the correct password and username.
4946 TestCompletionCallback callback4;
4947 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4948 EXPECT_EQ(ERR_IO_PENDING, rv);
4949 rv = callback4.WaitForResult();
4950 EXPECT_EQ(OK, rv);
4951 response = trans->GetResponseInfo();
4952 ASSERT_FALSE(response == NULL);
4953 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4954}
4955
[email protected]564b4912010-03-09 16:30:424956TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424957 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:064958 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:424959
[email protected]564b4912010-03-09 16:30:424960 SessionDependencies session_deps;
4961
4962 MockRead data_reads[] = {
4963 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]31e2c69e2010-04-15 18:06:064964 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424965 MockRead("hello world"),
4966 MockRead(false, OK),
4967 };
4968
4969 HttpRequestInfo request;
4970 request.method = "GET";
4971 request.url = GURL("http://www.google.com/");
4972 request.load_flags = 0;
4973
4974 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4975
4976 session_deps.socket_factory.AddSocketDataProvider(&data);
4977
4978 TestCompletionCallback callback;
4979
4980 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4981 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4982
[email protected]5a1d7ca2010-04-28 20:12:274983 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:424984 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534985
[email protected]564b4912010-03-09 16:30:424986 HostPortPair http_host_port_pair;
4987 http_host_port_pair.host = "www.google.com";
4988 http_host_port_pair.port = 80;
4989 const HttpAlternateProtocols& alternate_protocols =
4990 session->alternate_protocols();
4991 EXPECT_FALSE(
4992 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4993
4994 EXPECT_EQ(OK, callback.WaitForResult());
4995
4996 const HttpResponseInfo* response = trans->GetResponseInfo();
4997 ASSERT_TRUE(response != NULL);
4998 ASSERT_TRUE(response->headers != NULL);
4999 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535000 EXPECT_FALSE(response->was_fetched_via_spdy);
5001 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575002 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:425003
5004 std::string response_data;
5005 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5006 EXPECT_EQ("hello world", response_data);
5007
5008 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5009 const HttpAlternateProtocols::PortProtocolPair alternate =
5010 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
5011 HttpAlternateProtocols::PortProtocolPair expected_alternate;
5012 expected_alternate.port = 443;
[email protected]31e2c69e2010-04-15 18:06:065013 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_1;
[email protected]564b4912010-03-09 16:30:425014 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:425015
[email protected]31e2c69e2010-04-15 18:06:065016 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:425017 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:425018}
5019
5020TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:065021 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:425022 SessionDependencies session_deps;
5023
5024 HttpRequestInfo request;
5025 request.method = "GET";
5026 request.url = GURL("http://www.google.com/");
5027 request.load_flags = 0;
5028
5029 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
5030 StaticSocketDataProvider first_data;
5031 first_data.set_connect_data(mock_connect);
5032 session_deps.socket_factory.AddSocketDataProvider(&first_data);
5033
5034 MockRead data_reads[] = {
5035 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5036 MockRead("hello world"),
5037 MockRead(true, OK),
5038 };
5039 StaticSocketDataProvider second_data(
5040 data_reads, arraysize(data_reads), NULL, 0);
5041 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5042
5043 // TODO(willchan): Delete this extra data provider. It's necessary due to a
5044 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
5045 // http://crbug.com/37454.
5046 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5047
5048 TestCompletionCallback callback;
5049
5050 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5051
5052 HostPortPair http_host_port_pair;
5053 http_host_port_pair.host = "www.google.com";
5054 http_host_port_pair.port = 80;
5055 HttpAlternateProtocols* alternate_protocols =
5056 session->mutable_alternate_protocols();
5057 alternate_protocols->SetAlternateProtocolFor(
5058 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]31e2c69e2010-04-15 18:06:065059 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:425060
5061 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5062
[email protected]5a1d7ca2010-04-28 20:12:275063 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425064 EXPECT_EQ(ERR_IO_PENDING, rv);
5065 EXPECT_EQ(OK, callback.WaitForResult());
5066
5067 const HttpResponseInfo* response = trans->GetResponseInfo();
5068 ASSERT_TRUE(response != NULL);
5069 ASSERT_TRUE(response->headers != NULL);
5070 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5071
5072 std::string response_data;
5073 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5074 EXPECT_EQ("hello world", response_data);
5075
5076 ASSERT_TRUE(
5077 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
5078 const HttpAlternateProtocols::PortProtocolPair alternate =
5079 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
5080 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:065081 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425082}
5083
5084// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
5085// says that it does SPDY, but it just does the TLS handshake, but the NPN
5086// response does not indicate SPDY, so we just do standard HTTPS over the port.
5087// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
5088// on the original port.
[email protected]a2cb8122010-03-10 17:22:425089// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
5090// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:535091//
[email protected]a2cb8122010-03-10 17:22:425092// HttpRequestInfo request;
5093// request.method = "GET";
5094// request.url = GURL("http://www.google.com/");
5095// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:535096//
[email protected]a2cb8122010-03-10 17:22:425097// MockRead data_reads[] = {
5098// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5099// MockRead("hello world"),
5100// MockRead(true, OK),
5101// };
5102// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5103// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:535104//
[email protected]a2cb8122010-03-10 17:22:425105// SSLSocketDataProvider ssl(true, OK);
5106// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:535107//
[email protected]a2cb8122010-03-10 17:22:425108// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:535109//
[email protected]a2cb8122010-03-10 17:22:425110// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:535111//
[email protected]a2cb8122010-03-10 17:22:425112// HostPortPair http_host_port_pair;
5113// http_host_port_pair.host = "www.google.com";
5114// http_host_port_pair.port = 80;
5115// HttpAlternateProtocols* alternate_protocols =
5116// session->mutable_alternate_protocols();
5117// alternate_protocols->SetAlternateProtocolFor(
5118// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065119// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:535120//
[email protected]a2cb8122010-03-10 17:22:425121// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:535122//
[email protected]5a1d7ca2010-04-28 20:12:275123// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:425124// EXPECT_EQ(ERR_IO_PENDING, rv);
5125// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:535126//
[email protected]a2cb8122010-03-10 17:22:425127// const HttpResponseInfo* response = trans->GetResponseInfo();
5128// ASSERT_TRUE(response != NULL);
5129// ASSERT_TRUE(response->headers != NULL);
5130// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535131//
[email protected]a2cb8122010-03-10 17:22:425132// std::string response_data;
5133// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5134// EXPECT_EQ("hello world", response_data);
5135// }
5136
5137TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:065138 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]2ff8b312010-04-26 22:20:545139 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115140 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]564b4912010-03-09 16:30:425141 SessionDependencies session_deps;
5142
5143 HttpRequestInfo request;
5144 request.method = "GET";
5145 request.url = GURL("http://www.google.com/");
5146 request.load_flags = 0;
5147
[email protected]a2cb8122010-03-10 17:22:425148 StaticSocketDataProvider first_tcp_connect;
5149 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5150
5151 SSLSocketDataProvider ssl(true, OK);
5152 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5153
[email protected]564b4912010-03-09 16:30:425154 MockRead data_reads[] = {
5155 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5156 MockRead("hello world"),
5157 MockRead(true, OK),
5158 };
[email protected]a2cb8122010-03-10 17:22:425159 StaticSocketDataProvider fallback_data(
5160 data_reads, arraysize(data_reads), NULL, 0);
5161 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425162
5163 TestCompletionCallback callback;
5164
5165 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5166
5167 HostPortPair http_host_port_pair;
5168 http_host_port_pair.host = "www.google.com";
5169 http_host_port_pair.port = 80;
5170 HttpAlternateProtocols* alternate_protocols =
5171 session->mutable_alternate_protocols();
5172 alternate_protocols->SetAlternateProtocolFor(
5173 http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065174 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:425175
5176 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5177
[email protected]5a1d7ca2010-04-28 20:12:275178 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425179 EXPECT_EQ(ERR_IO_PENDING, rv);
5180 EXPECT_EQ(OK, callback.WaitForResult());
5181
5182 const HttpResponseInfo* response = trans->GetResponseInfo();
5183 ASSERT_TRUE(response != NULL);
5184 ASSERT_TRUE(response->headers != NULL);
5185 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5186
5187 std::string response_data;
5188 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5189 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:545190 HttpNetworkTransaction::SetNextProtos("");
5191 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5192}
5193
5194TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
5195 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5196 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115197 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545198 SessionDependencies session_deps;
5199
5200 HttpRequestInfo request;
5201 request.method = "GET";
5202 request.url = GURL("http://www.google.com/");
5203 request.load_flags = 0;
5204
5205 MockRead data_reads[] = {
5206 MockRead("HTTP/1.1 200 OK\r\n"),
5207 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5208 MockRead("hello world"),
5209 MockRead(true, OK),
5210 };
5211
5212 StaticSocketDataProvider first_transaction(
5213 data_reads, arraysize(data_reads), NULL, 0);
5214 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5215
5216 SSLSocketDataProvider ssl(true, OK);
5217 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5218 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535219 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545220 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5221
[email protected]75f30cc22010-06-28 21:41:385222 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0));
[email protected]e7f75092010-07-01 22:39:135223 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545224
[email protected]75f30cc22010-06-28 21:41:385225 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0));
[email protected]a4aeaf42010-06-30 19:57:285226 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame());
[email protected]2ff8b312010-04-26 22:20:545227 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135228 CreateMockRead(*resp),
5229 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545230 MockRead(true, 0, 0),
5231 };
5232
5233 scoped_refptr<DelayedSocketData> spdy_data(
5234 new DelayedSocketData(
5235 1, // wait for one write to finish before reading.
5236 spdy_reads, arraysize(spdy_reads),
5237 spdy_writes, arraysize(spdy_writes)));
5238 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5239
5240 TestCompletionCallback callback;
5241
5242 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5243 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5244
[email protected]5a1d7ca2010-04-28 20:12:275245 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545246 EXPECT_EQ(ERR_IO_PENDING, rv);
5247 EXPECT_EQ(OK, callback.WaitForResult());
5248
5249 const HttpResponseInfo* response = trans->GetResponseInfo();
5250 ASSERT_TRUE(response != NULL);
5251 ASSERT_TRUE(response->headers != NULL);
5252 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5253
5254 std::string response_data;
5255 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5256 EXPECT_EQ("hello world", response_data);
5257
5258 trans.reset(new HttpNetworkTransaction(session));
5259
[email protected]5a1d7ca2010-04-28 20:12:275260 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545261 EXPECT_EQ(ERR_IO_PENDING, rv);
5262 EXPECT_EQ(OK, callback.WaitForResult());
5263
5264 response = trans->GetResponseInfo();
5265 ASSERT_TRUE(response != NULL);
5266 ASSERT_TRUE(response->headers != NULL);
5267 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535268 EXPECT_TRUE(response->was_fetched_via_spdy);
5269 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575270 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545271
5272 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5273 EXPECT_EQ("hello!", response_data);
5274
5275 HttpNetworkTransaction::SetNextProtos("");
5276 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5277}
5278
[email protected]631f1322010-04-30 17:59:115279class CapturingProxyResolver : public ProxyResolver {
5280 public:
5281 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5282 virtual ~CapturingProxyResolver() {}
5283
5284 virtual int GetProxyForURL(const GURL& url,
5285 ProxyInfo* results,
5286 CompletionCallback* callback,
5287 RequestHandle* request,
5288 const BoundNetLog& net_log) {
[email protected]d911f1b2010-05-05 22:39:425289 ProxyServer proxy_server(
5290 ProxyServer::SCHEME_HTTP, "myproxy", 80);
5291 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115292 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425293 return OK;
[email protected]631f1322010-04-30 17:59:115294 }
5295
5296 virtual void CancelRequest(RequestHandle request) {
5297 NOTREACHED();
5298 }
5299
5300 const std::vector<GURL>& resolved() const { return resolved_; }
5301
5302 private:
5303 virtual int SetPacScript(const GURL& /*pac_url*/,
[email protected]9b9ae9552010-07-01 22:20:505304 const string16& /*pac_script*/,
[email protected]631f1322010-04-30 17:59:115305 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425306 return OK;
[email protected]631f1322010-04-30 17:59:115307 }
5308
5309 std::vector<GURL> resolved_;
5310
5311 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5312};
5313
[email protected]631f1322010-04-30 17:59:115314TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
5315 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5316 HttpNetworkTransaction::SetNextProtos(
5317 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
5318
5319 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425320 proxy_config.set_auto_detect(true);
5321 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115322
[email protected]631f1322010-04-30 17:59:115323 CapturingProxyResolver* capturing_proxy_resolver =
5324 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:385325 SessionDependencies session_deps(new ProxyService(
5326 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
5327 NULL));
[email protected]631f1322010-04-30 17:59:115328
5329 HttpRequestInfo request;
5330 request.method = "GET";
5331 request.url = GURL("http://www.google.com/");
5332 request.load_flags = 0;
5333
5334 MockRead data_reads[] = {
5335 MockRead("HTTP/1.1 200 OK\r\n"),
5336 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5337 MockRead("hello world"),
5338 MockRead(true, OK),
5339 };
5340
5341 StaticSocketDataProvider first_transaction(
5342 data_reads, arraysize(data_reads), NULL, 0);
5343 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5344
5345 SSLSocketDataProvider ssl(true, OK);
5346 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5347 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535348 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:115349 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5350
[email protected]75f30cc22010-06-28 21:41:385351 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0));
[email protected]631f1322010-04-30 17:59:115352 MockWrite spdy_writes[] = {
5353 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5354 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425355 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:135356 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:115357 };
5358
[email protected]d911f1b2010-05-05 22:39:425359 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5360
[email protected]75f30cc22010-06-28 21:41:385361 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0));
[email protected]a4aeaf42010-06-30 19:57:285362 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame());
[email protected]631f1322010-04-30 17:59:115363 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425364 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:135365 CreateMockRead(*resp.get(), 4), // 2, 4
5366 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:425367 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115368 };
5369
[email protected]d911f1b2010-05-05 22:39:425370 scoped_refptr<OrderedSocketData> spdy_data(
5371 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115372 spdy_reads, arraysize(spdy_reads),
5373 spdy_writes, arraysize(spdy_writes)));
5374 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5375
5376 TestCompletionCallback callback;
5377
5378 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5379 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5380
5381 int rv = trans->Start(&request, &callback, BoundNetLog());
5382 EXPECT_EQ(ERR_IO_PENDING, rv);
5383 EXPECT_EQ(OK, callback.WaitForResult());
5384
5385 const HttpResponseInfo* response = trans->GetResponseInfo();
5386 ASSERT_TRUE(response != NULL);
5387 ASSERT_TRUE(response->headers != NULL);
5388 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535389 EXPECT_FALSE(response->was_fetched_via_spdy);
5390 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115391
5392 std::string response_data;
5393 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5394 EXPECT_EQ("hello world", response_data);
5395
5396 trans.reset(new HttpNetworkTransaction(session));
5397
5398 rv = trans->Start(&request, &callback, BoundNetLog());
5399 EXPECT_EQ(ERR_IO_PENDING, rv);
5400 EXPECT_EQ(OK, callback.WaitForResult());
5401
5402 response = trans->GetResponseInfo();
5403 ASSERT_TRUE(response != NULL);
5404 ASSERT_TRUE(response->headers != NULL);
5405 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535406 EXPECT_TRUE(response->was_fetched_via_spdy);
5407 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115408
5409 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5410 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425411 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5412 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115413 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425414 EXPECT_EQ("https://www.google.com/",
5415 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115416
5417 HttpNetworkTransaction::SetNextProtos("");
5418 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5419}
[email protected]631f1322010-04-30 17:59:115420
[email protected]2ff8b312010-04-26 22:20:545421TEST_F(HttpNetworkTransactionTest,
5422 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5423 HttpNetworkTransaction::SetUseAlternateProtocols(true);
5424 HttpNetworkTransaction::SetNextProtos(
[email protected]2227c692010-05-04 15:36:115425 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]2ff8b312010-04-26 22:20:545426 SessionDependencies session_deps;
5427
5428 HttpRequestInfo request;
5429 request.method = "GET";
5430 request.url = GURL("http://www.google.com/");
5431 request.load_flags = 0;
5432
5433 MockRead data_reads[] = {
5434 MockRead("HTTP/1.1 200 OK\r\n"),
5435 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
5436 MockRead("hello world"),
5437 MockRead(true, OK),
5438 };
5439
5440 StaticSocketDataProvider first_transaction(
5441 data_reads, arraysize(data_reads), NULL, 0);
5442 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5443
5444 SSLSocketDataProvider ssl(true, OK);
5445 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
5446 ssl.next_proto = "spdy/1";
[email protected]65041fa2010-05-21 06:56:535447 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545448 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:535449 // Make sure we use ssl for spdy here.
5450 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:545451
[email protected]75f30cc22010-06-28 21:41:385452 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0));
[email protected]e7f75092010-07-01 22:39:135453 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545454
[email protected]75f30cc22010-06-28 21:41:385455 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0));
[email protected]a4aeaf42010-06-30 19:57:285456 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame());
[email protected]2ff8b312010-04-26 22:20:545457 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135458 CreateMockRead(*resp),
5459 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545460 MockRead(true, 0, 0),
5461 };
5462
5463 scoped_refptr<DelayedSocketData> spdy_data(
5464 new DelayedSocketData(
5465 1, // wait for one write to finish before reading.
5466 spdy_reads, arraysize(spdy_reads),
5467 spdy_writes, arraysize(spdy_writes)));
5468 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5469
5470 TestCompletionCallback callback;
5471
5472 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5473
5474 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5475
[email protected]5a1d7ca2010-04-28 20:12:275476 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545477 EXPECT_EQ(ERR_IO_PENDING, rv);
5478 EXPECT_EQ(OK, callback.WaitForResult());
5479
5480 const HttpResponseInfo* response = trans->GetResponseInfo();
5481 ASSERT_TRUE(response != NULL);
5482 ASSERT_TRUE(response->headers != NULL);
5483 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5484
5485 std::string response_data;
5486 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5487 EXPECT_EQ("hello world", response_data);
5488
5489 // Set up an initial SpdySession in the pool to reuse.
5490 scoped_refptr<SpdySession> spdy_session =
5491 session->spdy_session_pool()->Get(HostPortPair("www.google.com", 443),
[email protected]635909f2010-05-12 18:19:365492 session, BoundNetLog());
[email protected]df4b4ef2010-07-12 18:25:215493 scoped_refptr<TCPSocketParams> tcp_params =
5494 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:365495 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:545496 trans.reset(new HttpNetworkTransaction(session));
5497
[email protected]5a1d7ca2010-04-28 20:12:275498 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545499 EXPECT_EQ(ERR_IO_PENDING, rv);
5500 EXPECT_EQ(OK, callback.WaitForResult());
5501
5502 response = trans->GetResponseInfo();
5503 ASSERT_TRUE(response != NULL);
5504 ASSERT_TRUE(response->headers != NULL);
5505 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535506 EXPECT_TRUE(response->was_fetched_via_spdy);
5507 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575508 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545509
5510 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5511 EXPECT_EQ("hello!", response_data);
5512
5513 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065514 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425515}
5516
[email protected]044de0642010-06-17 10:42:155517// GenerateAuthToken is a mighty big test.
5518// It tests all permutation of GenerateAuthToken behavior:
5519// - Synchronous and Asynchronous completion.
5520// - OK or error on completion.
5521// - Direct connection, non-authenticating proxy, and authenticating proxy.
5522// - HTTP or HTTPS backend (to include proxy tunneling).
5523// - Non-authenticating and authenticating backend.
5524//
5525// In all, there are 44 reasonable permuations (for example, if there are
5526// problems generating an auth token for an authenticating proxy, we don't
5527// need to test all permutations of the backend server).
5528//
5529// The test proceeds by going over each of the configuration cases, and
5530// potentially running up to three rounds in each of the tests. The TestConfig
5531// specifies both the configuration for the test as well as the expectations
5532// for the results.
5533TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
5534 const char* kServer = "http://www.example.com";
5535 const char* kSecureServer = "https://www.example.com";
5536 const char* kProxy = "myproxy:70";
5537 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
5538
5539 enum AuthTiming {
5540 AUTH_NONE,
5541 AUTH_SYNC,
5542 AUTH_ASYNC,
5543 };
5544
5545 const MockWrite kGet(
5546 "GET / HTTP/1.1\r\n"
5547 "Host: www.example.com\r\n"
5548 "Connection: keep-alive\r\n\r\n");
5549 const MockWrite kGetProxy(
5550 "GET http://www.example.com/ HTTP/1.1\r\n"
5551 "Host: www.example.com\r\n"
5552 "Proxy-Connection: keep-alive\r\n\r\n");
5553 const MockWrite kGetAuth(
5554 "GET / HTTP/1.1\r\n"
5555 "Host: www.example.com\r\n"
5556 "Connection: keep-alive\r\n"
5557 "Authorization: auth_token\r\n\r\n");
5558 const MockWrite kGetProxyAuth(
5559 "GET http://www.example.com/ HTTP/1.1\r\n"
5560 "Host: www.example.com\r\n"
5561 "Proxy-Connection: keep-alive\r\n"
5562 "Proxy-Authorization: auth_token\r\n\r\n");
5563 const MockWrite kGetAuthThroughProxy(
5564 "GET http://www.example.com/ HTTP/1.1\r\n"
5565 "Host: www.example.com\r\n"
5566 "Proxy-Connection: keep-alive\r\n"
5567 "Authorization: auth_token\r\n\r\n");
5568 const MockWrite kGetAuthWithProxyAuth(
5569 "GET http://www.example.com/ HTTP/1.1\r\n"
5570 "Host: www.example.com\r\n"
5571 "Proxy-Connection: keep-alive\r\n"
5572 "Proxy-Authorization: auth_token\r\n"
5573 "Authorization: auth_token\r\n\r\n");
5574 const MockWrite kConnect(
5575 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5576 "Host: www.example.com\r\n"
5577 "Proxy-Connection: keep-alive\r\n\r\n");
5578 const MockWrite kConnectProxyAuth(
5579 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5580 "Host: www.example.com\r\n"
5581 "Proxy-Connection: keep-alive\r\n"
5582 "Proxy-Authorization: auth_token\r\n\r\n");
5583
5584 const MockRead kSuccess(
5585 "HTTP/1.1 200 OK\r\n"
5586 "Content-Type: text/html; charset=iso-8859-1\r\n"
5587 "Content-Length: 3\r\n\r\n"
5588 "Yes");
5589 const MockRead kFailure(
5590 "Should not be called.");
5591 const MockRead kServerChallenge(
5592 "HTTP/1.1 401 Unauthorized\r\n"
5593 "WWW-Authenticate: Mock realm=server\r\n"
5594 "Content-Type: text/html; charset=iso-8859-1\r\n"
5595 "Content-Length: 14\r\n\r\n"
5596 "Unauthorized\r\n");
5597 const MockRead kProxyChallenge(
5598 "HTTP/1.1 407 Unauthorized\r\n"
5599 "Proxy-Authenticate: Mock realm=proxy\r\n"
5600 "Proxy-Connection: close\r\n"
5601 "Content-Type: text/html; charset=iso-8859-1\r\n"
5602 "Content-Length: 14\r\n\r\n"
5603 "Unauthorized\r\n");
5604 const MockRead kProxyConnected(
5605 "HTTP/1.1 200 Connection Established\r\n\r\n");
5606
5607 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
5608 // no constructors, but the C++ compiler on Windows warns about
5609 // unspecified data in compound literals. So, moved to using constructors,
5610 // and TestRound's created with the default constructor should not be used.
5611 struct TestRound {
5612 TestRound()
5613 : expected_rv(ERR_UNEXPECTED),
5614 extra_write(NULL),
5615 extra_read(NULL) {
5616 }
5617 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5618 int expected_rv_arg)
5619 : write(write_arg),
5620 read(read_arg),
5621 expected_rv(expected_rv_arg),
5622 extra_write(NULL),
5623 extra_read(NULL) {
5624 }
5625 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5626 int expected_rv_arg, const MockWrite* extra_write_arg,
5627 const MockWrite* extra_read_arg)
5628 : write(write_arg),
5629 read(read_arg),
5630 expected_rv(expected_rv_arg),
5631 extra_write(extra_write_arg),
5632 extra_read(extra_read_arg) {
5633 }
5634 MockWrite write;
5635 MockRead read;
5636 int expected_rv;
5637 const MockWrite* extra_write;
5638 const MockRead* extra_read;
5639 };
5640
5641 static const int kNoSSL = 500;
5642
5643 struct TestConfig {
5644 const char* proxy_url;
5645 AuthTiming proxy_auth_timing;
5646 int proxy_auth_rv;
5647 const char* server_url;
5648 AuthTiming server_auth_timing;
5649 int server_auth_rv;
5650 int num_auth_rounds;
5651 int first_ssl_round;
5652 TestRound rounds[3];
5653 } test_configs[] = {
5654 // Non-authenticating HTTP server with a direct connection.
5655 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5656 { TestRound(kGet, kSuccess, OK)}},
5657 // Authenticating HTTP server with a direct connection.
5658 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5659 { TestRound(kGet, kServerChallenge, OK),
5660 TestRound(kGetAuth, kSuccess, OK)}},
5661 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5662 { TestRound(kGet, kServerChallenge, OK),
5663 TestRound(kGetAuth, kFailure, kAuthErr)}},
5664 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5665 { TestRound(kGet, kServerChallenge, OK),
5666 TestRound(kGetAuth, kSuccess, OK)}},
5667 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5668 { TestRound(kGet, kServerChallenge, OK),
5669 TestRound(kGetAuth, kFailure, kAuthErr)}},
5670 // Non-authenticating HTTP server through a non-authenticating proxy.
5671 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5672 { TestRound(kGetProxy, kSuccess, OK)}},
5673 // Authenticating HTTP server through a non-authenticating proxy.
5674 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5675 { TestRound(kGetProxy, kServerChallenge, OK),
5676 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5677 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5678 { TestRound(kGetProxy, kServerChallenge, OK),
5679 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5680 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5681 { TestRound(kGetProxy, kServerChallenge, OK),
5682 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5683 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5684 { TestRound(kGetProxy, kServerChallenge, OK),
5685 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5686 // Non-authenticating HTTP server through an authenticating proxy.
5687 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5688 { TestRound(kGetProxy, kProxyChallenge, OK),
5689 TestRound(kGetProxyAuth, kSuccess, OK)}},
5690 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5691 { TestRound(kGetProxy, kProxyChallenge, OK),
5692 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5693 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5694 { TestRound(kGetProxy, kProxyChallenge, OK),
5695 TestRound(kGetProxyAuth, kSuccess, OK)}},
5696 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5697 { TestRound(kGetProxy, kProxyChallenge, OK),
5698 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5699 // Authenticating HTTP server through an authenticating proxy.
5700 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5701 { TestRound(kGetProxy, kProxyChallenge, OK),
5702 TestRound(kGetProxyAuth, kServerChallenge, OK),
5703 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5704 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5705 { TestRound(kGetProxy, kProxyChallenge, OK),
5706 TestRound(kGetProxyAuth, kServerChallenge, OK),
5707 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5708 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5709 { TestRound(kGetProxy, kProxyChallenge, OK),
5710 TestRound(kGetProxyAuth, kServerChallenge, OK),
5711 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5712 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5713 { TestRound(kGetProxy, kProxyChallenge, OK),
5714 TestRound(kGetProxyAuth, kServerChallenge, OK),
5715 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5716 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5717 { TestRound(kGetProxy, kProxyChallenge, OK),
5718 TestRound(kGetProxyAuth, kServerChallenge, OK),
5719 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5720 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5721 { TestRound(kGetProxy, kProxyChallenge, OK),
5722 TestRound(kGetProxyAuth, kServerChallenge, OK),
5723 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5724 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5725 { TestRound(kGetProxy, kProxyChallenge, OK),
5726 TestRound(kGetProxyAuth, kServerChallenge, OK),
5727 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5728 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5729 { TestRound(kGetProxy, kProxyChallenge, OK),
5730 TestRound(kGetProxyAuth, kServerChallenge, OK),
5731 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5732 // Non-authenticating HTTPS server with a direct connection.
5733 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5734 { TestRound(kGet, kSuccess, OK)}},
5735 // Authenticating HTTPS server with a direct connection.
5736 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5737 { TestRound(kGet, kServerChallenge, OK),
5738 TestRound(kGetAuth, kSuccess, OK)}},
5739 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5740 { TestRound(kGet, kServerChallenge, OK),
5741 TestRound(kGetAuth, kFailure, kAuthErr)}},
5742 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5743 { TestRound(kGet, kServerChallenge, OK),
5744 TestRound(kGetAuth, kSuccess, OK)}},
5745 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5746 { TestRound(kGet, kServerChallenge, OK),
5747 TestRound(kGetAuth, kFailure, kAuthErr)}},
5748 // Non-authenticating HTTPS server with a non-authenticating proxy.
5749 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5750 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
5751 // Authenticating HTTPS server through a non-authenticating proxy.
5752 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5753 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5754 TestRound(kGetAuth, kSuccess, OK)}},
5755 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5756 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5757 TestRound(kGetAuth, kFailure, kAuthErr)}},
5758 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5759 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5760 TestRound(kGetAuth, kSuccess, OK)}},
5761 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5762 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5763 TestRound(kGetAuth, kFailure, kAuthErr)}},
5764 // Non-Authenticating HTTPS server through an authenticating proxy.
5765 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5766 { TestRound(kConnect, kProxyChallenge, OK),
5767 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5768 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5769 { TestRound(kConnect, kProxyChallenge, OK),
5770 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5771 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5772 { TestRound(kConnect, kProxyChallenge, OK),
5773 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5774 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5775 { TestRound(kConnect, kProxyChallenge, OK),
5776 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5777 // Authenticating HTTPS server through an authenticating proxy.
5778 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5779 { TestRound(kConnect, kProxyChallenge, OK),
5780 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5781 &kGet, &kServerChallenge),
5782 TestRound(kGetAuth, kSuccess, OK)}},
5783 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5784 { TestRound(kConnect, kProxyChallenge, OK),
5785 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5786 &kGet, &kServerChallenge),
5787 TestRound(kGetAuth, kFailure, kAuthErr)}},
5788 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5789 { TestRound(kConnect, kProxyChallenge, OK),
5790 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5791 &kGet, &kServerChallenge),
5792 TestRound(kGetAuth, kSuccess, OK)}},
5793 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5794 { TestRound(kConnect, kProxyChallenge, OK),
5795 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5796 &kGet, &kServerChallenge),
5797 TestRound(kGetAuth, kFailure, kAuthErr)}},
5798 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5799 { TestRound(kConnect, kProxyChallenge, OK),
5800 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5801 &kGet, &kServerChallenge),
5802 TestRound(kGetAuth, kSuccess, OK)}},
5803 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5804 { TestRound(kConnect, kProxyChallenge, OK),
5805 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5806 &kGet, &kServerChallenge),
5807 TestRound(kGetAuth, kFailure, kAuthErr)}},
5808 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5809 { TestRound(kConnect, kProxyChallenge, OK),
5810 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5811 &kGet, &kServerChallenge),
5812 TestRound(kGetAuth, kSuccess, OK)}},
5813 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5814 { TestRound(kConnect, kProxyChallenge, OK),
5815 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5816 &kGet, &kServerChallenge),
5817 TestRound(kGetAuth, kFailure, kAuthErr)}},
5818 };
5819
5820 SessionDependencies session_deps;
5821 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]3fd9dae2010-06-21 11:39:005822 HttpAuthHandlerMock::Factory* auth_factory(
5823 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:155824 session_deps.http_auth_handler_factory.reset(auth_factory);
5825
5826 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
5827 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:265828
5829 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:155830 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005831 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155832 std::string auth_challenge = "Mock realm=proxy";
5833 GURL origin(test_config.proxy_url);
5834 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5835 auth_challenge.end());
5836 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
5837 origin, BoundNetLog());
5838 auth_handler->SetGenerateExpectation(
5839 test_config.proxy_auth_timing == AUTH_ASYNC,
5840 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:155841 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
5842 }
5843 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005844 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155845 std::string auth_challenge = "Mock realm=server";
5846 GURL origin(test_config.server_url);
5847 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5848 auth_challenge.end());
5849 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
5850 origin, BoundNetLog());
5851 auth_handler->SetGenerateExpectation(
5852 test_config.server_auth_timing == AUTH_ASYNC,
5853 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:155854 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
5855 }
5856 if (test_config.proxy_url) {
5857 session_deps.proxy_service =
5858 CreateFixedProxyService(test_config.proxy_url);
5859 } else {
5860 session_deps.proxy_service = ProxyService::CreateNull();
5861 }
5862
5863 HttpRequestInfo request;
5864 request.method = "GET";
5865 request.url = GURL(test_config.server_url);
5866 request.load_flags = 0;
5867
5868 scoped_ptr<HttpTransaction> trans(
5869 new HttpNetworkTransaction(CreateSession(&session_deps)));
5870
5871 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
5872 const TestRound& read_write_round = test_config.rounds[round];
5873
5874 // Set up expected reads and writes.
5875 MockRead reads[2];
5876 reads[0] = read_write_round.read;
5877 size_t length_reads = 1;
5878 if (read_write_round.extra_read) {
5879 reads[1] = *read_write_round.extra_read;
5880 length_reads = 2;
5881 }
5882
5883 MockWrite writes[2];
5884 writes[0] = read_write_round.write;
5885 size_t length_writes = 1;
5886 if (read_write_round.extra_write) {
5887 writes[1] = *read_write_round.extra_write;
5888 length_writes = 2;
5889 }
5890 StaticSocketDataProvider data_provider(
5891 reads, length_reads, writes, length_writes);
5892 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
5893
5894 // Add an SSL sequence if necessary.
5895 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
5896 if (round >= test_config.first_ssl_round)
5897 session_deps.socket_factory.AddSSLSocketDataProvider(
5898 &ssl_socket_data_provider);
5899
5900 // Start or restart the transaction.
5901 TestCompletionCallback callback;
5902 int rv;
5903 if (round == 0) {
5904 rv = trans->Start(&request, &callback, BoundNetLog());
5905 } else {
5906 rv = trans->RestartWithAuth(L"foo", L"bar", &callback);
5907 }
5908 if (rv == ERR_IO_PENDING)
5909 rv = callback.WaitForResult();
5910
5911 // Compare results with expected data.
5912 EXPECT_EQ(read_write_round.expected_rv, rv);
5913 const HttpResponseInfo* response = trans->GetResponseInfo();
5914 if (read_write_round.expected_rv == OK) {
5915 EXPECT_FALSE(response == NULL);
5916 } else {
5917 EXPECT_TRUE(response == NULL);
5918 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
5919 continue;
5920 }
5921 if (round + 1 < test_config.num_auth_rounds) {
5922 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5923 } else {
5924 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5925 }
5926 }
[email protected]e5ae96a2010-04-14 20:12:455927 }
[email protected]e60e47a2010-07-14 03:37:185928
5929 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
5930 session->FlushSocketPools();
[email protected]e5ae96a2010-04-14 20:12:455931}
5932
[email protected]aeaca1f2010-04-20 22:05:215933class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
5934 public:
[email protected]06650c52010-06-03 00:49:175935 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:215936 : fail_all_(fail_all) {
5937 }
5938
5939 virtual MockRead GetNextRead() {
5940 if (fail_all_)
5941 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
5942
5943 return MockRead(false /* async */,
5944 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
5945 }
5946
5947 virtual MockWriteResult OnWrite(const std::string& data) {
5948 return MockWriteResult(false /* async */, data.size());
5949 }
5950
5951 void Reset() {
5952 }
5953
5954 private:
5955 const bool fail_all_;
5956};
5957
5958// Test that we restart a connection when we see a decompression failure from
5959// the peer during the handshake. (In the real world we'll restart with SSLv3
5960// and we won't offer DEFLATE in that case.)
5961TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
5962 HttpRequestInfo request;
5963 request.method = "GET";
5964 request.url = GURL("https://tlsdecompressionfailure.example.com/");
5965 request.load_flags = 0;
5966
5967 SessionDependencies session_deps;
5968 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5969 false /* fail all reads */);
5970 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5971 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:115972 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:215973 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5974 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5975 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5976 session_deps.socket_factory.AddSSLSocketDataProvider(
5977 &ssl_socket_data_provider1);
5978 session_deps.socket_factory.AddSSLSocketDataProvider(
5979 &ssl_socket_data_provider2);
5980
[email protected]e60e47a2010-07-14 03:37:185981 // Work around http://crbug.com/37454
5982 StaticSocketDataProvider bug37454_connection;
5983 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
5984 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
5985
[email protected]aeaca1f2010-04-20 22:05:215986 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5987 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5988 TestCompletionCallback callback;
5989
[email protected]5a1d7ca2010-04-28 20:12:275990 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:215991 EXPECT_EQ(ERR_IO_PENDING, rv);
5992 EXPECT_EQ(OK, callback.WaitForResult());
5993
5994 const HttpResponseInfo* response = trans->GetResponseInfo();
5995 ASSERT_TRUE(response != NULL);
5996 ASSERT_TRUE(response->headers != NULL);
5997 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5998
5999 std::string response_data;
6000 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6001 EXPECT_EQ("ok.", response_data);
6002}
6003
6004// Test that we restart a connection if we get a decompression failure from the
6005// peer while reading the first bytes from the connection. This occurs when the
6006// peer cannot handle DEFLATE but we're using False Start, so we don't notice
6007// in the handshake.
6008TEST_F(HttpNetworkTransactionTest,
6009 RestartAfterTLSDecompressionFailureWithFalseStart) {
6010 HttpRequestInfo request;
6011 request.method = "GET";
6012 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
6013 request.load_flags = 0;
6014
6015 SessionDependencies session_deps;
6016 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6017 true /* fail all reads */);
6018 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6019 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
6020 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6021 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6022 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6023 session_deps.socket_factory.AddSSLSocketDataProvider(
6024 &ssl_socket_data_provider1);
6025 session_deps.socket_factory.AddSSLSocketDataProvider(
6026 &ssl_socket_data_provider2);
6027
6028 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6029 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6030 TestCompletionCallback callback;
6031
[email protected]5a1d7ca2010-04-28 20:12:276032 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216033 EXPECT_EQ(ERR_IO_PENDING, rv);
6034 EXPECT_EQ(OK, callback.WaitForResult());
6035
6036 const HttpResponseInfo* response = trans->GetResponseInfo();
6037 ASSERT_TRUE(response != NULL);
6038 ASSERT_TRUE(response->headers != NULL);
6039 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6040
6041 std::string response_data;
6042 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6043 EXPECT_EQ("ok.", response_data);
6044}
6045
[email protected]65041fa2010-05-21 06:56:536046// This tests the case that a request is issued via http instead of spdy after
6047// npn is negotiated.
6048TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
6049 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6050 HttpNetworkTransaction::SetNextProtos("\x08http/1.1\x07http1.1");
6051 SessionDependencies session_deps;
6052 HttpRequestInfo request;
6053 request.method = "GET";
6054 request.url = GURL("https://www.google.com/");
6055 request.load_flags = 0;
6056
6057 MockWrite data_writes[] = {
6058 MockWrite("GET / HTTP/1.1\r\n"
6059 "Host: www.google.com\r\n"
6060 "Connection: keep-alive\r\n\r\n"),
6061 };
6062
6063 MockRead data_reads[] = {
6064 MockRead("HTTP/1.1 200 OK\r\n"),
6065 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
6066 MockRead("hello world"),
6067 MockRead(false, OK),
6068 };
6069
6070 SSLSocketDataProvider ssl(true, OK);
6071 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6072 ssl.next_proto = "http/1.1";
6073
6074 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6075
6076 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6077 data_writes, arraysize(data_writes));
6078 session_deps.socket_factory.AddSocketDataProvider(&data);
6079
6080 TestCompletionCallback callback;
6081
6082 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6083 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6084
6085 int rv = trans->Start(&request, &callback, BoundNetLog());
6086
6087 EXPECT_EQ(ERR_IO_PENDING, rv);
6088 EXPECT_EQ(OK, callback.WaitForResult());
6089
6090 const HttpResponseInfo* response = trans->GetResponseInfo();
6091 ASSERT_TRUE(response != NULL);
6092 ASSERT_TRUE(response->headers != NULL);
6093 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6094
6095 std::string response_data;
6096 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6097 EXPECT_EQ("hello world", response_data);
6098
6099 EXPECT_FALSE(response->was_fetched_via_spdy);
6100 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576101 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:536102
6103 HttpNetworkTransaction::SetNextProtos("");
6104 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6105}
[email protected]26ef6582010-06-24 02:30:476106
6107TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
6108 // Simulate the SSL handshake completing with an NPN negotiation
6109 // followed by an immediate server closing of the socket.
6110 // Fix crash: http://crbug.com/46369
6111 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6112 HttpNetworkTransaction::SetNextProtos(
6113 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
6114 SessionDependencies session_deps;
6115
6116 HttpRequestInfo request;
6117 request.method = "GET";
6118 request.url = GURL("https://www.google.com/");
6119 request.load_flags = 0;
6120
6121 SSLSocketDataProvider ssl(true, OK);
6122 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6123 ssl.next_proto = "spdy/1";
6124 ssl.was_npn_negotiated = true;
6125 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6126
[email protected]75f30cc22010-06-28 21:41:386127 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0));
[email protected]e7f75092010-07-01 22:39:136128 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:476129
6130 MockRead spdy_reads[] = {
6131 MockRead(false, 0, 0) // Not async - return 0 immediately.
6132 };
6133
6134 scoped_refptr<DelayedSocketData> spdy_data(
6135 new DelayedSocketData(
6136 0, // don't wait in this case, immediate hangup.
6137 spdy_reads, arraysize(spdy_reads),
6138 spdy_writes, arraysize(spdy_writes)));
6139 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6140
6141 TestCompletionCallback callback;
6142
6143 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6144 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6145
6146 int rv = trans->Start(&request, &callback, BoundNetLog());
6147 EXPECT_EQ(ERR_IO_PENDING, rv);
6148 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
6149
6150 HttpNetworkTransaction::SetNextProtos("");
6151 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6152}
[email protected]65d34382010-07-01 18:12:266153
[email protected]89ceba9a2009-03-21 03:46:066154} // namespace net