blob: 72fa8aa43cf7462a7dbe12b6c02a8614d2551a54 [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]13c8a092010-07-29 06:15:4447namespace {
48
49const string16 kBar(ASCIIToUTF16("bar"));
50const string16 kBar2(ASCIIToUTF16("bar2"));
51const string16 kBar3(ASCIIToUTF16("bar3"));
52const string16 kBaz(ASCIIToUTF16("baz"));
53const string16 kFirst(ASCIIToUTF16("first"));
54const string16 kFoo(ASCIIToUTF16("foo"));
55const string16 kFoo2(ASCIIToUTF16("foo2"));
56const string16 kFoo3(ASCIIToUTF16("foo3"));
57const string16 kFou(ASCIIToUTF16("fou"));
58const string16 kSecond(ASCIIToUTF16("second"));
59const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
60const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
61
62} // namespace
63
[email protected]89ceba9a2009-03-21 03:46:0664namespace net {
65
[email protected]2d731a32010-04-29 01:04:0666class HttpNetworkSessionPeer {
67 public:
68 explicit HttpNetworkSessionPeer(
69 const scoped_refptr<HttpNetworkSession>& session)
70 : session_(session) {}
71
72 void SetTCPSocketPool(const scoped_refptr<TCPClientSocketPool>& pool) {
73 session_->tcp_socket_pool_ = pool;
74 }
75
76 void SetSocketPoolForSOCKSProxy(
77 const HostPortPair& socks_proxy,
78 const scoped_refptr<SOCKSClientSocketPool>& pool) {
[email protected]e60e47a2010-07-14 03:37:1879 session_->socks_socket_pools_[socks_proxy] = pool;
[email protected]2d731a32010-04-29 01:04:0680 }
81
82 void SetSocketPoolForHTTPProxy(
83 const HostPortPair& http_proxy,
[email protected]e772db3f2010-07-12 18:11:1384 const scoped_refptr<HttpProxyClientSocketPool>& pool) {
[email protected]e60e47a2010-07-14 03:37:1885 session_->http_proxy_socket_pools_[http_proxy] = pool;
86 }
87
88 void SetSSLSocketPool(const scoped_refptr<SSLClientSocketPool>& pool) {
89 session_->ssl_socket_pool_ = pool;
90 }
91
92 void SetSocketPoolForSSLWithProxy(
93 const HostPortPair& proxy_host,
94 const scoped_refptr<SSLClientSocketPool>& pool) {
95 session_->ssl_socket_pools_for_proxies_[proxy_host] = pool;
[email protected]2d731a32010-04-29 01:04:0696 }
97
98 private:
99 const scoped_refptr<HttpNetworkSession> session_;
100
101 DISALLOW_COPY_AND_ASSIGN(HttpNetworkSessionPeer);
102};
103
[email protected]e44de5d2009-06-05 20:12:45104// Helper to manage the lifetimes of the dependencies for a
105// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:44106struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:59107 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:42108 SessionDependencies()
109 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:37110 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:10111 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:52112 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]a7ea8832010-07-12 17:54:54113 spdy_session_pool(new SpdySessionPool()),
114 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59115
116 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:45117 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:42118 : host_resolver(new MockHostResolver),
119 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:10120 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:52121 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]a7ea8832010-07-12 17:54:54122 spdy_session_pool(new SpdySessionPool()),
123 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59124
[email protected]a2c2fb92009-07-18 07:31:04125 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:09126 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:42127 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:59128 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50129 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a554a8262010-05-20 00:13:52130 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]a7ea8832010-07-12 17:54:54131 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59132};
133
[email protected]1c773ea12009-04-28 19:58:42134ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50135 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48136 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39137 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53138}
139
[email protected]228ff742009-06-05 01:19:59140HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]66761b952010-06-25 21:30:38141 return new HttpNetworkSession(session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:09142 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42143 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10144 session_deps->ssl_config_service,
[email protected]a554a8262010-05-20 00:13:52145 session_deps->spdy_session_pool,
[email protected]06650c52010-06-03 00:49:17146 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44147 NULL,
[email protected]a7ea8832010-07-12 17:54:54148 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14149}
150
[email protected]89836e22008-09-25 20:33:42151class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52152 public:
[email protected]2ff8b312010-04-26 22:20:54153 virtual void SetUp() {
154 spdy::SpdyFramer::set_enable_compression_default(false);
155 }
156
[email protected]0e75a732008-10-16 20:36:09157 virtual void TearDown() {
[email protected]2ff8b312010-04-26 22:20:54158 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09159 // Empty the current queue.
160 MessageLoop::current()->RunAllPending();
161 PlatformTest::TearDown();
162 }
163
[email protected]3d2a59b2008-09-26 19:44:25164 protected:
165 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52166
[email protected]ff007e162009-05-23 09:13:15167 struct SimpleGetHelperResult {
168 int rv;
169 std::string status_line;
170 std::string response_data;
171 };
initial.commit586acc5fe2008-07-26 22:42:52172
[email protected]31a2bfe2010-02-09 08:03:39173 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
174 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15175 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52176
[email protected]228ff742009-06-05 01:19:59177 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40178 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43179 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52180
[email protected]ff007e162009-05-23 09:13:15181 HttpRequestInfo request;
182 request.method = "GET";
183 request.url = GURL("http://www.google.com/");
184 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52185
[email protected]31a2bfe2010-02-09 08:03:39186 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59187 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52188
[email protected]ff007e162009-05-23 09:13:15189 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52190
[email protected]169d0012010-05-10 23:20:12191 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
192 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15193 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52194
[email protected]ff007e162009-05-23 09:13:15195 out.rv = callback.WaitForResult();
196 if (out.rv != OK)
197 return out;
198
199 const HttpResponseInfo* response = trans->GetResponseInfo();
200 EXPECT_TRUE(response != NULL);
201
202 EXPECT_TRUE(response->headers != NULL);
203 out.status_line = response->headers->GetStatusLine();
204
205 rv = ReadTransaction(trans.get(), &out.response_data);
206 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39207 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12208 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
209 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39210 ExpectLogContainsSomewhere(
211 log.entries(), pos,
212 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
213 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15214
[email protected]aecfbf22008-10-16 02:02:47215 return out;
[email protected]ff007e162009-05-23 09:13:15216 }
initial.commit586acc5fe2008-07-26 22:42:52217
[email protected]ff007e162009-05-23 09:13:15218 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
219 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52220
[email protected]ff007e162009-05-23 09:13:15221 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15222};
[email protected]231d5a32008-09-13 00:45:27223
[email protected]15a5ccf82008-10-23 19:57:43224// Fill |str| with a long header list that consumes >= |size| bytes.
225void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19226 const char* row =
227 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
228 const int sizeof_row = strlen(row);
229 const int num_rows = static_cast<int>(
230 ceil(static_cast<float>(size) / sizeof_row));
231 const int sizeof_data = num_rows * sizeof_row;
232 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43233 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51234
[email protected]4ddaf2502008-10-23 18:26:19235 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43236 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19237}
238
[email protected]385a4672009-03-11 22:21:29239// Alternative functions that eliminate randomness and dependency on the local
240// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20241void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29242 static const uint8 bytes[] = {
243 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
244 };
245 static size_t current_byte = 0;
246 for (size_t i = 0; i < n; ++i) {
247 output[i] = bytes[current_byte++];
248 current_byte %= arraysize(bytes);
249 }
250}
251
[email protected]fe2bc6a2009-03-23 16:52:20252void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29253 static const uint8 bytes[] = {
254 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
255 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
256 };
257 static size_t current_byte = 0;
258 for (size_t i = 0; i < n; ++i) {
259 output[i] = bytes[current_byte++];
260 current_byte %= arraysize(bytes);
261 }
262}
263
[email protected]fe2bc6a2009-03-23 16:52:20264std::string MockGetHostName() {
265 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29266}
267
[email protected]e60e47a2010-07-14 03:37:18268template<typename ParentPool>
269class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31270 public:
[email protected]e60e47a2010-07-14 03:37:18271 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
272
[email protected]d80a4322009-08-14 07:07:49273 const std::string last_group_name_received() const {
274 return last_group_name_;
275 }
276
[email protected]684970b2009-08-14 04:54:46277 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49278 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31279 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31280 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46281 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53282 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31283 last_group_name_ = group_name;
284 return ERR_IO_PENDING;
285 }
[email protected]04e5be32009-06-26 20:00:31286 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21287 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31288 virtual void ReleaseSocket(const std::string& group_name,
289 ClientSocket* socket) {}
290 virtual void CloseIdleSockets() {}
291 virtual HostResolver* GetHostResolver() const {
292 return NULL;
293 }
294 virtual int IdleSocketCount() const {
295 return 0;
296 }
297 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
298 return 0;
299 }
300 virtual LoadState GetLoadState(const std::string& group_name,
301 const ClientSocketHandle* handle) const {
302 return LOAD_STATE_IDLE;
303 }
[email protected]a796bcec2010-03-22 17:17:26304 virtual base::TimeDelta ConnectionTimeout() const {
305 return base::TimeDelta();
306 }
[email protected]d80a4322009-08-14 07:07:49307
308 private:
[email protected]04e5be32009-06-26 20:00:31309 std::string last_group_name_;
310};
311
[email protected]2d731a32010-04-29 01:04:06312typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11313CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13314typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
315CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06316typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11317CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18318typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
319CaptureGroupNameSSLSocketPool;
320
321template<typename ParentPool>
322CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
323 HttpNetworkSession* session)
324 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
325
326template<>
327CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
328 HttpNetworkSession* session)
329 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
330 NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11331
[email protected]231d5a32008-09-13 00:45:27332//-----------------------------------------------------------------------------
333
[email protected]dae22c52010-07-30 02:16:35334// This is the expected list of advertised protocols from the browser's NPN
335// list.
336static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
337
338// This is the expected return from a current server advertising SPDY.
339static const char kAlternateProtocolHttpHeader[] =
340 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
341
[email protected]231d5a32008-09-13 00:45:27342TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59343 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40344 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43345 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27346}
347
348TEST_F(HttpNetworkTransactionTest, SimpleGET) {
349 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35350 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
351 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42352 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27353 };
[email protected]31a2bfe2010-02-09 08:03:39354 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
355 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42356 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27357 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
358 EXPECT_EQ("hello world", out.response_data);
359}
360
361// Response with no status line.
362TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
363 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35364 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42365 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27366 };
[email protected]31a2bfe2010-02-09 08:03:39367 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
368 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42369 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27370 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
371 EXPECT_EQ("hello world", out.response_data);
372}
373
374// Allow up to 4 bytes of junk to precede status line.
375TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
376 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35377 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42378 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27379 };
[email protected]31a2bfe2010-02-09 08:03:39380 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
381 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42382 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27383 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
384 EXPECT_EQ("DATA", out.response_data);
385}
386
387// Allow up to 4 bytes of junk to precede status line.
388TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
389 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35390 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42391 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27392 };
[email protected]31a2bfe2010-02-09 08:03:39393 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
394 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42395 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27396 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
397 EXPECT_EQ("DATA", out.response_data);
398}
399
400// Beyond 4 bytes of slop and it should fail to find a status line.
401TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
402 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35403 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42404 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27405 };
[email protected]31a2bfe2010-02-09 08:03:39406 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
407 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42408 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25409 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
410 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27411}
412
413// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
414TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
415 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35416 MockRead("\n"),
417 MockRead("\n"),
418 MockRead("Q"),
419 MockRead("J"),
420 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42421 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27422 };
[email protected]31a2bfe2010-02-09 08:03:39423 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
424 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42425 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27426 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
427 EXPECT_EQ("DATA", out.response_data);
428}
429
430// Close the connection before enough bytes to have a status line.
431TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
432 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35433 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42434 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27435 };
[email protected]31a2bfe2010-02-09 08:03:39436 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
437 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42438 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27439 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
440 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52441}
442
[email protected]f9d44aa2008-09-23 23:57:17443// Simulate a 204 response, lacking a Content-Length header, sent over a
444// persistent connection. The response should still terminate since a 204
445// cannot have a response body.
446TEST_F(HttpNetworkTransactionTest, StopsReading204) {
447 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35448 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
449 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42450 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17451 };
[email protected]31a2bfe2010-02-09 08:03:39452 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
453 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42454 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17455 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
456 EXPECT_EQ("", out.response_data);
457}
458
[email protected]0877e3d2009-10-17 22:29:57459// A simple request using chunked encoding with some extra data after.
460// (Like might be seen in a pipelined response.)
461TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
462 MockRead data_reads[] = {
463 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
464 MockRead("5\r\nHello\r\n"),
465 MockRead("1\r\n"),
466 MockRead(" \r\n"),
467 MockRead("5\r\nworld\r\n"),
468 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
469 MockRead(false, OK),
470 };
[email protected]31a2bfe2010-02-09 08:03:39471 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
472 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57473 EXPECT_EQ(OK, out.rv);
474 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
475 EXPECT_EQ("Hello world", out.response_data);
476}
477
[email protected]ef0faf2e72009-03-05 23:27:23478// Do a request using the HEAD method. Verify that we don't try to read the
479// message body (since HEAD has none).
480TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59481 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40482 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43483 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23484
[email protected]1c773ea12009-04-28 19:58:42485 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23486 request.method = "HEAD";
487 request.url = GURL("http://www.google.com/");
488 request.load_flags = 0;
489
490 MockWrite data_writes1[] = {
491 MockWrite("HEAD / HTTP/1.1\r\n"
492 "Host: www.google.com\r\n"
493 "Connection: keep-alive\r\n"
494 "Content-Length: 0\r\n\r\n"),
495 };
496 MockRead data_reads1[] = {
497 MockRead("HTTP/1.1 404 Not Found\r\n"),
498 MockRead("Server: Blah\r\n"),
499 MockRead("Content-Length: 1234\r\n\r\n"),
500
501 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42502 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23503 };
504
[email protected]31a2bfe2010-02-09 08:03:39505 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
506 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59507 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23508
509 TestCompletionCallback callback1;
510
[email protected]5a1d7ca2010-04-28 20:12:27511 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42512 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23513
514 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42515 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23516
[email protected]1c773ea12009-04-28 19:58:42517 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23518 EXPECT_FALSE(response == NULL);
519
520 // Check that the headers got parsed.
521 EXPECT_TRUE(response->headers != NULL);
522 EXPECT_EQ(1234, response->headers->GetContentLength());
523 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
524
525 std::string server_header;
526 void* iter = NULL;
527 bool has_server_header = response->headers->EnumerateHeader(
528 &iter, "Server", &server_header);
529 EXPECT_TRUE(has_server_header);
530 EXPECT_EQ("Blah", server_header);
531
532 // Reading should give EOF right away, since there is no message body
533 // (despite non-zero content-length).
534 std::string response_data;
535 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42536 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23537 EXPECT_EQ("", response_data);
538}
539
initial.commit586acc5fe2008-07-26 22:42:52540TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59541 SessionDependencies session_deps;
542 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52543
544 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35545 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
546 MockRead("hello"),
547 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
548 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42549 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52550 };
[email protected]31a2bfe2010-02-09 08:03:39551 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59552 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52553
554 const char* kExpectedResponseData[] = {
555 "hello", "world"
556 };
557
558 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43559 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52560
[email protected]1c773ea12009-04-28 19:58:42561 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52562 request.method = "GET";
563 request.url = GURL("http://www.google.com/");
564 request.load_flags = 0;
565
566 TestCompletionCallback callback;
567
[email protected]5a1d7ca2010-04-28 20:12:27568 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42569 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52570
571 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42572 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52573
[email protected]1c773ea12009-04-28 19:58:42574 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52575 EXPECT_TRUE(response != NULL);
576
577 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25578 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52579
580 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57581 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42582 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25583 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52584 }
585}
586
587TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59588 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40589 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43590 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52591
[email protected]1c773ea12009-04-28 19:58:42592 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52593 request.method = "POST";
594 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42595 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52596 request.upload_data->AppendBytes("foo", 3);
597 request.load_flags = 0;
598
599 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35600 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
601 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
602 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42603 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52604 };
[email protected]31a2bfe2010-02-09 08:03:39605 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59606 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52607
608 TestCompletionCallback callback;
609
[email protected]5a1d7ca2010-04-28 20:12:27610 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42611 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52612
613 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42614 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52615
[email protected]1c773ea12009-04-28 19:58:42616 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52617 EXPECT_TRUE(response != NULL);
618
619 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25620 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52621
622 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57623 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42624 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25625 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52626}
627
[email protected]3a2d3662009-03-27 03:49:14628// This test is almost the same as Ignores100 above, but the response contains
629// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57630// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14631TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59632 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40633 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43634 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14635
[email protected]1c773ea12009-04-28 19:58:42636 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14637 request.method = "GET";
638 request.url = GURL("http://www.foo.com/");
639 request.load_flags = 0;
640
641 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57642 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
643 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14644 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42645 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14646 };
[email protected]31a2bfe2010-02-09 08:03:39647 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59648 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14649
650 TestCompletionCallback callback;
651
[email protected]5a1d7ca2010-04-28 20:12:27652 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42653 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14654
655 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42656 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14657
[email protected]1c773ea12009-04-28 19:58:42658 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14659 EXPECT_TRUE(response != NULL);
660
661 EXPECT_TRUE(response->headers != NULL);
662 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
663
664 std::string response_data;
665 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42666 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14667 EXPECT_EQ("hello world", response_data);
668}
669
[email protected]ee9410e72010-01-07 01:42:38670TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
671 SessionDependencies session_deps;
672 scoped_ptr<HttpTransaction> trans(
673 new HttpNetworkTransaction(CreateSession(&session_deps)));
674
675 HttpRequestInfo request;
676 request.method = "POST";
677 request.url = GURL("http://www.foo.com/");
678 request.load_flags = 0;
679
680 MockRead data_reads[] = {
681 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
682 MockRead(true, 0),
683 };
[email protected]31a2bfe2010-02-09 08:03:39684 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38685 session_deps.socket_factory.AddSocketDataProvider(&data);
686
687 TestCompletionCallback callback;
688
[email protected]5a1d7ca2010-04-28 20:12:27689 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38690 EXPECT_EQ(ERR_IO_PENDING, rv);
691
692 rv = callback.WaitForResult();
693 EXPECT_EQ(OK, rv);
694
695 std::string response_data;
696 rv = ReadTransaction(trans.get(), &response_data);
697 EXPECT_EQ(OK, rv);
698 EXPECT_EQ("", response_data);
699}
700
701TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
702 SessionDependencies session_deps;
703 scoped_ptr<HttpTransaction> trans(
704 new HttpNetworkTransaction(CreateSession(&session_deps)));
705
706 HttpRequestInfo request;
707 request.method = "POST";
708 request.url = GURL("http://www.foo.com/");
709 request.load_flags = 0;
710
711 MockRead data_reads[] = {
712 MockRead(true, 0),
713 };
[email protected]31a2bfe2010-02-09 08:03:39714 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38715 session_deps.socket_factory.AddSocketDataProvider(&data);
716
717 TestCompletionCallback callback;
718
[email protected]5a1d7ca2010-04-28 20:12:27719 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38720 EXPECT_EQ(ERR_IO_PENDING, rv);
721
722 rv = callback.WaitForResult();
723 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
724}
725
[email protected]3d2a59b2008-09-26 19:44:25726// read_failure specifies a read failure that should cause the network
727// transaction to resend the request.
728void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
729 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59730 SessionDependencies session_deps;
731 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52732
[email protected]1c773ea12009-04-28 19:58:42733 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52734 request.method = "GET";
735 request.url = GURL("http://www.foo.com/");
736 request.load_flags = 0;
737
738 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35739 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
740 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25741 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52742 };
[email protected]31a2bfe2010-02-09 08:03:39743 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59744 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52745
746 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35747 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
748 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42749 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52750 };
[email protected]31a2bfe2010-02-09 08:03:39751 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59752 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52753
754 const char* kExpectedResponseData[] = {
755 "hello", "world"
756 };
757
758 for (int i = 0; i < 2; ++i) {
759 TestCompletionCallback callback;
760
[email protected]5695b8c2009-09-30 21:36:43761 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52762
[email protected]5a1d7ca2010-04-28 20:12:27763 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42764 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52765
766 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42767 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52768
[email protected]1c773ea12009-04-28 19:58:42769 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52770 EXPECT_TRUE(response != NULL);
771
772 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25773 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52774
775 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57776 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42777 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25778 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52779 }
780}
[email protected]3d2a59b2008-09-26 19:44:25781
782TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42783 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25784 KeepAliveConnectionResendRequestTest(read_failure);
785}
786
787TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42788 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25789 KeepAliveConnectionResendRequestTest(read_failure);
790}
791
792TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59793 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40794 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43795 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25796
[email protected]1c773ea12009-04-28 19:58:42797 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25798 request.method = "GET";
799 request.url = GURL("http://www.google.com/");
800 request.load_flags = 0;
801
802 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42803 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35804 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
805 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42806 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25807 };
[email protected]31a2bfe2010-02-09 08:03:39808 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59809 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25810
811 TestCompletionCallback callback;
812
[email protected]5a1d7ca2010-04-28 20:12:27813 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42814 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25815
816 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42817 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25818
[email protected]1c773ea12009-04-28 19:58:42819 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25820 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25821}
822
823// What do various browsers do when the server closes a non-keepalive
824// connection without sending any response header or body?
825//
826// IE7: error page
827// Safari 3.1.2 (Windows): error page
828// Firefox 3.0.1: blank page
829// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42830// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
831// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25832TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
833 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42834 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35835 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
836 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42837 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25838 };
[email protected]31a2bfe2010-02-09 08:03:39839 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
840 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42841 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25842}
[email protected]038e9a32008-10-08 22:40:16843
[email protected]fc31d6a42010-06-24 18:05:13844// Test that we correctly reuse a keep-alive connection after receiving a 304.
845TEST_F(HttpNetworkTransactionTest, KeepAliveAfter304) {
846 SessionDependencies session_deps;
847 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
848
849 HttpRequestInfo request;
850 request.method = "GET";
851 request.url = GURL("http://www.foo.com/");
852 request.load_flags = 0;
853
854 MockRead data1_reads[] = {
855 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
856 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
857 MockRead("hello"),
858 };
859 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
860 session_deps.socket_factory.AddSocketDataProvider(&data1);
861
862 MockRead data2_reads[] = {
863 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
864 };
865 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
866 session_deps.socket_factory.AddSocketDataProvider(&data2);
867
868 for (int i = 0; i < 2; ++i) {
869 TestCompletionCallback callback;
870
871 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
872
873 int rv = trans->Start(&request, &callback, BoundNetLog());
874 EXPECT_EQ(ERR_IO_PENDING, rv);
875
876 rv = callback.WaitForResult();
877 EXPECT_EQ(OK, rv);
878
879 const HttpResponseInfo* response = trans->GetResponseInfo();
880 EXPECT_TRUE(response != NULL);
881
882 EXPECT_TRUE(response->headers != NULL);
883 if (i == 0) {
884 EXPECT_EQ("HTTP/1.1 304 Not Modified",
885 response->headers->GetStatusLine());
886 // We intentionally don't read the response in this case, to reflect how
887 // HttpCache::Transaction uses HttpNetworkTransaction.
888 } else {
889 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
890 std::string response_data;
891 rv = ReadTransaction(trans.get(), &response_data);
892 EXPECT_EQ(OK, rv);
893 EXPECT_EQ("hello", response_data);
894 }
895 }
896}
897
[email protected]038e9a32008-10-08 22:40:16898// Test the request-challenge-retry sequence for basic auth.
899// (basic auth is the easiest to mock, because it has no randomness).
900TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59901 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40902 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43903 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16904
[email protected]1c773ea12009-04-28 19:58:42905 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16906 request.method = "GET";
907 request.url = GURL("http://www.google.com/");
908 request.load_flags = 0;
909
[email protected]f9ee6b52008-11-08 06:46:23910 MockWrite data_writes1[] = {
911 MockWrite("GET / HTTP/1.1\r\n"
912 "Host: www.google.com\r\n"
913 "Connection: keep-alive\r\n\r\n"),
914 };
915
[email protected]038e9a32008-10-08 22:40:16916 MockRead data_reads1[] = {
917 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
918 // Give a couple authenticate options (only the middle one is actually
919 // supported).
[email protected]22927ad2009-09-21 19:56:19920 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16921 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
922 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
923 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
924 // Large content-length -- won't matter, as connection will be reset.
925 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42926 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16927 };
928
929 // After calling trans->RestartWithAuth(), this is the request we should
930 // be issuing -- the final header line contains the credentials.
931 MockWrite data_writes2[] = {
932 MockWrite("GET / HTTP/1.1\r\n"
933 "Host: www.google.com\r\n"
934 "Connection: keep-alive\r\n"
935 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
936 };
937
938 // Lastly, the server responds with the actual content.
939 MockRead data_reads2[] = {
940 MockRead("HTTP/1.0 200 OK\r\n"),
941 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
942 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42943 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16944 };
945
[email protected]31a2bfe2010-02-09 08:03:39946 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
947 data_writes1, arraysize(data_writes1));
948 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
949 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59950 session_deps.socket_factory.AddSocketDataProvider(&data1);
951 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16952
953 TestCompletionCallback callback1;
954
[email protected]5a1d7ca2010-04-28 20:12:27955 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42956 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16957
958 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42959 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16960
[email protected]1c773ea12009-04-28 19:58:42961 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16962 EXPECT_FALSE(response == NULL);
963
964 // The password prompt info should have been set in response->auth_challenge.
965 EXPECT_FALSE(response->auth_challenge.get() == NULL);
966
[email protected]71e4573a2009-05-21 22:03:00967 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16968 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
969 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
970
971 TestCompletionCallback callback2;
972
[email protected]13c8a092010-07-29 06:15:44973 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:42974 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16975
976 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42977 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16978
979 response = trans->GetResponseInfo();
980 EXPECT_FALSE(response == NULL);
981 EXPECT_TRUE(response->auth_challenge.get() == NULL);
982 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16983}
984
[email protected]861fcd52009-08-26 02:33:46985TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
986 SessionDependencies session_deps;
987 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43988 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46989
990 HttpRequestInfo request;
991 request.method = "GET";
992 request.url = GURL("http://www.google.com/");
993 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
994
995 MockWrite data_writes[] = {
996 MockWrite("GET / HTTP/1.1\r\n"
997 "Host: www.google.com\r\n"
998 "Connection: keep-alive\r\n\r\n"),
999 };
1000
1001 MockRead data_reads[] = {
1002 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1003 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1004 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1005 // Large content-length -- won't matter, as connection will be reset.
1006 MockRead("Content-Length: 10000\r\n\r\n"),
1007 MockRead(false, ERR_FAILED),
1008 };
1009
[email protected]31a2bfe2010-02-09 08:03:391010 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1011 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591012 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461013 TestCompletionCallback callback;
1014
[email protected]5a1d7ca2010-04-28 20:12:271015 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461016 EXPECT_EQ(ERR_IO_PENDING, rv);
1017
1018 rv = callback.WaitForResult();
1019 EXPECT_EQ(0, rv);
1020
1021 const HttpResponseInfo* response = trans->GetResponseInfo();
1022 ASSERT_FALSE(response == NULL);
1023 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1024}
1025
[email protected]2d2697f92009-02-18 21:00:321026// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1027// connection.
1028TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:591029 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401030 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431031 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321032
[email protected]1c773ea12009-04-28 19:58:421033 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321034 request.method = "GET";
1035 request.url = GURL("http://www.google.com/");
1036 request.load_flags = 0;
1037
1038 MockWrite data_writes1[] = {
1039 MockWrite("GET / HTTP/1.1\r\n"
1040 "Host: www.google.com\r\n"
1041 "Connection: keep-alive\r\n\r\n"),
1042
1043 // After calling trans->RestartWithAuth(), this is the request we should
1044 // be issuing -- the final header line contains the credentials.
1045 MockWrite("GET / HTTP/1.1\r\n"
1046 "Host: www.google.com\r\n"
1047 "Connection: keep-alive\r\n"
1048 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1049 };
1050
1051 MockRead data_reads1[] = {
1052 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1053 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1054 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1055 MockRead("Content-Length: 14\r\n\r\n"),
1056 MockRead("Unauthorized\r\n"),
1057
1058 // Lastly, the server responds with the actual content.
1059 MockRead("HTTP/1.1 200 OK\r\n"),
1060 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1061 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421062 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321063 };
1064
[email protected]31a2bfe2010-02-09 08:03:391065 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1066 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591067 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321068
1069 TestCompletionCallback callback1;
1070
[email protected]5a1d7ca2010-04-28 20:12:271071 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421072 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321073
1074 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421075 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321076
[email protected]1c773ea12009-04-28 19:58:421077 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321078 EXPECT_FALSE(response == NULL);
1079
1080 // The password prompt info should have been set in response->auth_challenge.
1081 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1082
[email protected]71e4573a2009-05-21 22:03:001083 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321084 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1085 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1086
1087 TestCompletionCallback callback2;
1088
[email protected]13c8a092010-07-29 06:15:441089 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421090 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321091
1092 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421093 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321094
1095 response = trans->GetResponseInfo();
1096 EXPECT_FALSE(response == NULL);
1097 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1098 EXPECT_EQ(100, response->headers->GetContentLength());
1099}
1100
1101// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1102// connection and with no response body to drain.
1103TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591104 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401105 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431106 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321107
[email protected]1c773ea12009-04-28 19:58:421108 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321109 request.method = "GET";
1110 request.url = GURL("http://www.google.com/");
1111 request.load_flags = 0;
1112
1113 MockWrite data_writes1[] = {
1114 MockWrite("GET / HTTP/1.1\r\n"
1115 "Host: www.google.com\r\n"
1116 "Connection: keep-alive\r\n\r\n"),
1117
1118 // After calling trans->RestartWithAuth(), this is the request we should
1119 // be issuing -- the final header line contains the credentials.
1120 MockWrite("GET / HTTP/1.1\r\n"
1121 "Host: www.google.com\r\n"
1122 "Connection: keep-alive\r\n"
1123 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1124 };
1125
[email protected]2d2697f92009-02-18 21:00:321126 MockRead data_reads1[] = {
1127 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1128 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311129 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321130
1131 // Lastly, the server responds with the actual content.
1132 MockRead("HTTP/1.1 200 OK\r\n"),
1133 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1134 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421135 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321136 };
1137
[email protected]31a2bfe2010-02-09 08:03:391138 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1139 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591140 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321141
1142 TestCompletionCallback callback1;
1143
[email protected]5a1d7ca2010-04-28 20:12:271144 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421145 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321146
1147 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421148 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321149
[email protected]1c773ea12009-04-28 19:58:421150 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321151 EXPECT_FALSE(response == NULL);
1152
1153 // The password prompt info should have been set in response->auth_challenge.
1154 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1155
[email protected]71e4573a2009-05-21 22:03:001156 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321157 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1158 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1159
1160 TestCompletionCallback callback2;
1161
[email protected]13c8a092010-07-29 06:15:441162 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421163 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321164
1165 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421166 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321167
1168 response = trans->GetResponseInfo();
1169 EXPECT_FALSE(response == NULL);
1170 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1171 EXPECT_EQ(100, response->headers->GetContentLength());
1172}
1173
1174// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1175// connection and with a large response body to drain.
1176TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591177 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401178 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431179 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321180
[email protected]1c773ea12009-04-28 19:58:421181 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321182 request.method = "GET";
1183 request.url = GURL("http://www.google.com/");
1184 request.load_flags = 0;
1185
1186 MockWrite data_writes1[] = {
1187 MockWrite("GET / HTTP/1.1\r\n"
1188 "Host: www.google.com\r\n"
1189 "Connection: keep-alive\r\n\r\n"),
1190
1191 // After calling trans->RestartWithAuth(), this is the request we should
1192 // be issuing -- the final header line contains the credentials.
1193 MockWrite("GET / HTTP/1.1\r\n"
1194 "Host: www.google.com\r\n"
1195 "Connection: keep-alive\r\n"
1196 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1197 };
1198
1199 // Respond with 5 kb of response body.
1200 std::string large_body_string("Unauthorized");
1201 large_body_string.append(5 * 1024, ' ');
1202 large_body_string.append("\r\n");
1203
1204 MockRead data_reads1[] = {
1205 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1206 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1207 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1208 // 5134 = 12 + 5 * 1024 + 2
1209 MockRead("Content-Length: 5134\r\n\r\n"),
1210 MockRead(true, large_body_string.data(), large_body_string.size()),
1211
1212 // Lastly, the server responds with the actual content.
1213 MockRead("HTTP/1.1 200 OK\r\n"),
1214 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1215 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421216 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321217 };
1218
[email protected]31a2bfe2010-02-09 08:03:391219 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1220 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591221 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321222
1223 TestCompletionCallback callback1;
1224
[email protected]5a1d7ca2010-04-28 20:12:271225 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421226 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321227
1228 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421229 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321230
[email protected]1c773ea12009-04-28 19:58:421231 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321232 EXPECT_FALSE(response == NULL);
1233
1234 // The password prompt info should have been set in response->auth_challenge.
1235 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1236
[email protected]71e4573a2009-05-21 22:03:001237 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321238 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1239 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1240
1241 TestCompletionCallback callback2;
1242
[email protected]13c8a092010-07-29 06:15:441243 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421244 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321245
1246 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421247 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321248
1249 response = trans->GetResponseInfo();
1250 EXPECT_FALSE(response == NULL);
1251 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1252 EXPECT_EQ(100, response->headers->GetContentLength());
1253}
1254
1255// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311256// connection, but the server gets impatient and closes the connection.
1257TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1258 SessionDependencies session_deps;
1259 scoped_ptr<HttpTransaction> trans(
1260 new HttpNetworkTransaction(CreateSession(&session_deps)));
1261
1262 HttpRequestInfo request;
1263 request.method = "GET";
1264 request.url = GURL("http://www.google.com/");
1265 request.load_flags = 0;
1266
1267 MockWrite data_writes1[] = {
1268 MockWrite("GET / HTTP/1.1\r\n"
1269 "Host: www.google.com\r\n"
1270 "Connection: keep-alive\r\n\r\n"),
1271 // This simulates the seemingly successful write to a closed connection
1272 // if the bug is not fixed.
1273 MockWrite("GET / HTTP/1.1\r\n"
1274 "Host: www.google.com\r\n"
1275 "Connection: keep-alive\r\n"
1276 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1277 };
1278
1279 MockRead data_reads1[] = {
1280 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1281 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1282 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1283 MockRead("Content-Length: 14\r\n\r\n"),
1284 // Tell MockTCPClientSocket to simulate the server closing the connection.
1285 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1286 MockRead("Unauthorized\r\n"),
1287 MockRead(false, OK), // The server closes the connection.
1288 };
1289
1290 // After calling trans->RestartWithAuth(), this is the request we should
1291 // be issuing -- the final header line contains the credentials.
1292 MockWrite data_writes2[] = {
1293 MockWrite("GET / HTTP/1.1\r\n"
1294 "Host: www.google.com\r\n"
1295 "Connection: keep-alive\r\n"
1296 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1297 };
1298
1299 // Lastly, the server responds with the actual content.
1300 MockRead data_reads2[] = {
1301 MockRead("HTTP/1.1 200 OK\r\n"),
1302 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1303 MockRead("Content-Length: 100\r\n\r\n"),
1304 MockRead(false, OK),
1305 };
1306
[email protected]31a2bfe2010-02-09 08:03:391307 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1308 data_writes1, arraysize(data_writes1));
1309 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1310 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311311 session_deps.socket_factory.AddSocketDataProvider(&data1);
1312 session_deps.socket_factory.AddSocketDataProvider(&data2);
1313
1314 TestCompletionCallback callback1;
1315
[email protected]5a1d7ca2010-04-28 20:12:271316 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311317 EXPECT_EQ(ERR_IO_PENDING, rv);
1318
1319 rv = callback1.WaitForResult();
1320 EXPECT_EQ(OK, rv);
1321
1322 const HttpResponseInfo* response = trans->GetResponseInfo();
1323 EXPECT_FALSE(response == NULL);
1324
1325 // The password prompt info should have been set in response->auth_challenge.
1326 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1327
1328 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1329 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1330 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1331
1332 TestCompletionCallback callback2;
1333
[email protected]13c8a092010-07-29 06:15:441334 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311335 EXPECT_EQ(ERR_IO_PENDING, rv);
1336
1337 rv = callback2.WaitForResult();
1338 EXPECT_EQ(OK, rv);
1339
1340 response = trans->GetResponseInfo();
1341 ASSERT_FALSE(response == NULL);
1342 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1343 EXPECT_EQ(100, response->headers->GetContentLength());
1344}
1345
1346// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321347// proxy connection, when setting up an SSL tunnel.
1348TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1349 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591350 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541351 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1352 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591353 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321354
[email protected]5695b8c2009-09-30 21:36:431355 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321356
[email protected]1c773ea12009-04-28 19:58:421357 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321358 request.method = "GET";
1359 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461360 // Ensure that proxy authentication is attempted even
1361 // when the no authentication data flag is set.
1362 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321363
1364 // Since we have proxy, should try to establish tunnel.
1365 MockWrite data_writes1[] = {
1366 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451367 "Host: www.google.com\r\n"
1368 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321369
1370 // After calling trans->RestartWithAuth(), this is the request we should
1371 // be issuing -- the final header line contains the credentials.
1372 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1373 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451374 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321375 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1376 };
1377
1378 // The proxy responds to the connect with a 407, using a persistent
1379 // connection.
1380 MockRead data_reads1[] = {
1381 // No credentials.
1382 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1383 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1384 MockRead("Content-Length: 10\r\n\r\n"),
1385 MockRead("0123456789"),
1386
1387 // Wrong credentials (wrong password).
1388 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1389 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1390 MockRead("Content-Length: 10\r\n\r\n"),
1391 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421392 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321393 };
1394
[email protected]31a2bfe2010-02-09 08:03:391395 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1396 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591397 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321398
1399 TestCompletionCallback callback1;
1400
[email protected]dbb83db2010-05-11 18:13:391401 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421402 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321403
1404 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421405 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391406 size_t pos = ExpectLogContainsSomewhere(
1407 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1408 NetLog::PHASE_NONE);
1409 ExpectLogContainsSomewhere(
1410 log.entries(), pos,
1411 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1412 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321413
[email protected]1c773ea12009-04-28 19:58:421414 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321415 EXPECT_FALSE(response == NULL);
1416
1417 EXPECT_TRUE(response->headers->IsKeepAlive());
1418 EXPECT_EQ(407, response->headers->response_code());
1419 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421420 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321421
1422 // The password prompt info should have been set in response->auth_challenge.
1423 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1424
[email protected]71e4573a2009-05-21 22:03:001425 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321426 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1427 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1428
1429 TestCompletionCallback callback2;
1430
1431 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441432 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421433 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321434
1435 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421436 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321437
1438 response = trans->GetResponseInfo();
1439 EXPECT_FALSE(response == NULL);
1440
1441 EXPECT_TRUE(response->headers->IsKeepAlive());
1442 EXPECT_EQ(407, response->headers->response_code());
1443 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421444 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321445
1446 // The password prompt info should have been set in response->auth_challenge.
1447 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1448
[email protected]71e4573a2009-05-21 22:03:001449 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321450 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1451 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131452
[email protected]e60e47a2010-07-14 03:37:181453 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1454 // out of scope.
1455 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321456}
1457
[email protected]a8e9b162009-03-12 00:06:441458// Test that we don't read the response body when we fail to establish a tunnel,
1459// even if the user cancels the proxy's auth attempt.
1460TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1461 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591462 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441463
[email protected]e44de5d2009-06-05 20:12:451464 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441465
[email protected]5695b8c2009-09-30 21:36:431466 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441467
[email protected]1c773ea12009-04-28 19:58:421468 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441469 request.method = "GET";
1470 request.url = GURL("https://www.google.com/");
1471 request.load_flags = 0;
1472
1473 // Since we have proxy, should try to establish tunnel.
1474 MockWrite data_writes[] = {
1475 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451476 "Host: www.google.com\r\n"
1477 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441478 };
1479
1480 // The proxy responds to the connect with a 407.
1481 MockRead data_reads[] = {
1482 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1483 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1484 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421485 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441486 };
1487
[email protected]31a2bfe2010-02-09 08:03:391488 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1489 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591490 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441491
1492 TestCompletionCallback callback;
1493
[email protected]5a1d7ca2010-04-28 20:12:271494 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421495 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441496
1497 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421498 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441499
[email protected]1c773ea12009-04-28 19:58:421500 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441501 EXPECT_FALSE(response == NULL);
1502
1503 EXPECT_TRUE(response->headers->IsKeepAlive());
1504 EXPECT_EQ(407, response->headers->response_code());
1505 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421506 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441507
1508 std::string response_data;
1509 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421510 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181511
1512 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1513 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441514}
1515
[email protected]8fdbcd22010-05-05 02:54:521516// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1517// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1518TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1519 // We are using a DIRECT connection (i.e. no proxy) for this session.
1520 SessionDependencies session_deps;
1521 scoped_ptr<HttpTransaction> trans(
1522 new HttpNetworkTransaction(CreateSession(&session_deps)));
1523
1524 HttpRequestInfo request;
1525 request.method = "GET";
1526 request.url = GURL("http://www.google.com/");
1527 request.load_flags = 0;
1528
1529 MockWrite data_writes1[] = {
1530 MockWrite("GET / HTTP/1.1\r\n"
1531 "Host: www.google.com\r\n"
1532 "Connection: keep-alive\r\n\r\n"),
1533 };
1534
1535 MockRead data_reads1[] = {
1536 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1537 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1538 // Large content-length -- won't matter, as connection will be reset.
1539 MockRead("Content-Length: 10000\r\n\r\n"),
1540 MockRead(false, ERR_FAILED),
1541 };
1542
1543 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1544 data_writes1, arraysize(data_writes1));
1545 session_deps.socket_factory.AddSocketDataProvider(&data1);
1546
1547 TestCompletionCallback callback;
1548
1549 int rv = trans->Start(&request, &callback, BoundNetLog());
1550 EXPECT_EQ(ERR_IO_PENDING, rv);
1551
1552 rv = callback.WaitForResult();
1553 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1554}
1555
[email protected]ff007e162009-05-23 09:13:151556void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081557 const MockRead& status, int expected_status) {
1558 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591559 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081560
[email protected]228ff742009-06-05 01:19:591561 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081562
[email protected]5695b8c2009-09-30 21:36:431563 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081564
[email protected]1c773ea12009-04-28 19:58:421565 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081566 request.method = "GET";
1567 request.url = GURL("https://www.google.com/");
1568 request.load_flags = 0;
1569
1570 // Since we have proxy, should try to establish tunnel.
1571 MockWrite data_writes[] = {
1572 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451573 "Host: www.google.com\r\n"
1574 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081575 };
1576
1577 MockRead data_reads[] = {
1578 status,
1579 MockRead("Content-Length: 10\r\n\r\n"),
1580 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421581 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081582 };
1583
[email protected]31a2bfe2010-02-09 08:03:391584 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1585 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591586 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081587
1588 TestCompletionCallback callback;
1589
[email protected]5a1d7ca2010-04-28 20:12:271590 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421591 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081592
1593 rv = callback.WaitForResult();
1594 EXPECT_EQ(expected_status, rv);
1595}
1596
[email protected]ff007e162009-05-23 09:13:151597void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081598 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421599 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081600}
1601
1602TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1603 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1604}
1605
1606TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1607 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1608}
1609
1610TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1611 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1612}
1613
1614TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1615 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1616}
1617
1618TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1619 ConnectStatusHelper(
1620 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1621}
1622
1623TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1624 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1625}
1626
1627TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1628 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1629}
1630
1631TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1632 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1633}
1634
1635TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1636 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1637}
1638
1639TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1640 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1641}
1642
1643TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1644 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1645}
1646
1647TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1648 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1649}
1650
1651TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1652 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1653}
1654
1655TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1656 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1657}
1658
1659TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1660 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1661}
1662
1663TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1664 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1665}
1666
1667TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1668 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1669}
1670
1671TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1672 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1673}
1674
1675TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1676 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1677}
1678
1679TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1680 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1681}
1682
1683TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1684 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1685}
1686
1687TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1688 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1689}
1690
1691TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1692 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1693}
1694
1695TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1696 ConnectStatusHelperWithExpectedStatus(
1697 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:541698 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:081699}
1700
1701TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1702 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1703}
1704
1705TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1706 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1707}
1708
1709TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1710 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1711}
1712
1713TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1714 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1715}
1716
1717TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1718 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1719}
1720
1721TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1722 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1723}
1724
1725TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1726 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1727}
1728
1729TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1730 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1731}
1732
1733TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1734 ConnectStatusHelper(
1735 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1736}
1737
1738TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1739 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1740}
1741
1742TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1743 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1744}
1745
1746TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1747 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1748}
1749
1750TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1751 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1752}
1753
1754TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1755 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1756}
1757
1758TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1759 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1760}
1761
1762TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1763 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1764}
1765
[email protected]038e9a32008-10-08 22:40:161766// Test the flow when both the proxy server AND origin server require
1767// authentication. Again, this uses basic auth for both since that is
1768// the simplest to mock.
1769TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591770 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011771
[email protected]038e9a32008-10-08 22:40:161772 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421773 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431774 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161775
[email protected]1c773ea12009-04-28 19:58:421776 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161777 request.method = "GET";
1778 request.url = GURL("http://www.google.com/");
1779 request.load_flags = 0;
1780
[email protected]f9ee6b52008-11-08 06:46:231781 MockWrite data_writes1[] = {
1782 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1783 "Host: www.google.com\r\n"
1784 "Proxy-Connection: keep-alive\r\n\r\n"),
1785 };
1786
[email protected]038e9a32008-10-08 22:40:161787 MockRead data_reads1[] = {
1788 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1789 // Give a couple authenticate options (only the middle one is actually
1790 // supported).
[email protected]22927ad2009-09-21 19:56:191791 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161792 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1793 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1794 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1795 // Large content-length -- won't matter, as connection will be reset.
1796 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421797 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161798 };
1799
1800 // After calling trans->RestartWithAuth() the first time, this is the
1801 // request we should be issuing -- the final header line contains the
1802 // proxy's credentials.
1803 MockWrite data_writes2[] = {
1804 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1805 "Host: www.google.com\r\n"
1806 "Proxy-Connection: keep-alive\r\n"
1807 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1808 };
1809
1810 // Now the proxy server lets the request pass through to origin server.
1811 // The origin server responds with a 401.
1812 MockRead data_reads2[] = {
1813 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1814 // Note: We are using the same realm-name as the proxy server. This is
1815 // completely valid, as realms are unique across hosts.
1816 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1817 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1818 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421819 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161820 };
1821
1822 // After calling trans->RestartWithAuth() the second time, we should send
1823 // the credentials for both the proxy and origin server.
1824 MockWrite data_writes3[] = {
1825 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1826 "Host: www.google.com\r\n"
1827 "Proxy-Connection: keep-alive\r\n"
1828 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1829 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1830 };
1831
1832 // Lastly we get the desired content.
1833 MockRead data_reads3[] = {
1834 MockRead("HTTP/1.0 200 OK\r\n"),
1835 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1836 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421837 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161838 };
1839
[email protected]31a2bfe2010-02-09 08:03:391840 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1841 data_writes1, arraysize(data_writes1));
1842 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1843 data_writes2, arraysize(data_writes2));
1844 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1845 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591846 session_deps.socket_factory.AddSocketDataProvider(&data1);
1847 session_deps.socket_factory.AddSocketDataProvider(&data2);
1848 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161849
1850 TestCompletionCallback callback1;
1851
[email protected]5a1d7ca2010-04-28 20:12:271852 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421853 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161854
1855 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421856 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161857
[email protected]1c773ea12009-04-28 19:58:421858 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161859 EXPECT_FALSE(response == NULL);
1860
1861 // The password prompt info should have been set in response->auth_challenge.
1862 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1863
[email protected]71e4573a2009-05-21 22:03:001864 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161865 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1866 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1867
1868 TestCompletionCallback callback2;
1869
[email protected]13c8a092010-07-29 06:15:441870 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421871 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161872
1873 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421874 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161875
1876 response = trans->GetResponseInfo();
1877 EXPECT_FALSE(response == NULL);
1878 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1879
[email protected]71e4573a2009-05-21 22:03:001880 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161881 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1882 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1883
1884 TestCompletionCallback callback3;
1885
[email protected]13c8a092010-07-29 06:15:441886 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:421887 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161888
1889 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421890 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161891
1892 response = trans->GetResponseInfo();
1893 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1894 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161895}
[email protected]4ddaf2502008-10-23 18:26:191896
[email protected]ea9dc9a2009-09-05 00:43:321897// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1898// can't hook into its internals to cause it to generate predictable NTLM
1899// authorization headers.
1900#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291901// The NTLM authentication unit tests were generated by capturing the HTTP
1902// requests and responses using Fiddler 2 and inspecting the generated random
1903// bytes in the debugger.
1904
1905// Enter the correct password and authenticate successfully.
1906TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421907 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:111908 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591909 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401910 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431911 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241912
[email protected]1c773ea12009-04-28 19:58:421913 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241914 request.method = "GET";
1915 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1916 request.load_flags = 0;
1917
1918 MockWrite data_writes1[] = {
1919 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1920 "Host: 172.22.68.17\r\n"
1921 "Connection: keep-alive\r\n\r\n"),
1922 };
1923
1924 MockRead data_reads1[] = {
1925 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:041926 // Negotiate and NTLM are often requested together. However, we only want
1927 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
1928 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:241929 MockRead("WWW-Authenticate: NTLM\r\n"),
1930 MockRead("Connection: close\r\n"),
1931 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361932 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241933 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421934 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241935 };
1936
1937 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221938 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241939 // request we should be issuing -- the final header line contains a Type
1940 // 1 message.
1941 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1942 "Host: 172.22.68.17\r\n"
1943 "Connection: keep-alive\r\n"
1944 "Authorization: NTLM "
1945 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1946
1947 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1948 // (the credentials for the origin server). The second request continues
1949 // on the same connection.
1950 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1951 "Host: 172.22.68.17\r\n"
1952 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291953 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1954 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1955 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1956 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1957 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241958 };
1959
1960 MockRead data_reads2[] = {
1961 // The origin server responds with a Type 2 message.
1962 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1963 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291964 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241965 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1966 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1967 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1968 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1969 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1970 "BtAAAAAAA=\r\n"),
1971 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361972 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241973 MockRead("You are not authorized to view this page\r\n"),
1974
1975 // Lastly we get the desired content.
1976 MockRead("HTTP/1.1 200 OK\r\n"),
1977 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1978 MockRead("Content-Length: 13\r\n\r\n"),
1979 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421980 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241981 };
1982
[email protected]31a2bfe2010-02-09 08:03:391983 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1984 data_writes1, arraysize(data_writes1));
1985 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1986 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591987 session_deps.socket_factory.AddSocketDataProvider(&data1);
1988 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241989
1990 TestCompletionCallback callback1;
1991
[email protected]5a1d7ca2010-04-28 20:12:271992 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421993 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241994
1995 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421996 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241997
[email protected]0757e7702009-03-27 04:00:221998 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1999 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442000 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422001 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222002 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422003 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222004 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2005
[email protected]1c773ea12009-04-28 19:58:422006 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042007 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242008
[email protected]aef04272010-06-28 18:03:042009 // The password prompt info should have been set in
2010 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242011 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2012
[email protected]71e4573a2009-05-21 22:03:002013 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242014 EXPECT_EQ(L"", response->auth_challenge->realm);
2015 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2016
[email protected]0757e7702009-03-27 04:00:222017 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242018
[email protected]13c8a092010-07-29 06:15:442019 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422020 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242021
[email protected]0757e7702009-03-27 04:00:222022 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422023 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242024
2025 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042026 ASSERT_FALSE(response == NULL);
2027
[email protected]3f918782009-02-28 01:29:242028 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2029 EXPECT_EQ(13, response->headers->GetContentLength());
2030}
2031
[email protected]385a4672009-03-11 22:21:292032// Enter a wrong password, and then the correct one.
2033TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422034 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112035 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592036 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402037 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432038 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:292039
[email protected]1c773ea12009-04-28 19:58:422040 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292041 request.method = "GET";
2042 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2043 request.load_flags = 0;
2044
2045 MockWrite data_writes1[] = {
2046 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2047 "Host: 172.22.68.17\r\n"
2048 "Connection: keep-alive\r\n\r\n"),
2049 };
2050
2051 MockRead data_reads1[] = {
2052 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042053 // Negotiate and NTLM are often requested together. However, we only want
2054 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2055 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292056 MockRead("WWW-Authenticate: NTLM\r\n"),
2057 MockRead("Connection: close\r\n"),
2058 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362059 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292060 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422061 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292062 };
2063
2064 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222065 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292066 // request we should be issuing -- the final header line contains a Type
2067 // 1 message.
2068 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2069 "Host: 172.22.68.17\r\n"
2070 "Connection: keep-alive\r\n"
2071 "Authorization: NTLM "
2072 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2073
2074 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2075 // (the credentials for the origin server). The second request continues
2076 // on the same connection.
2077 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2078 "Host: 172.22.68.17\r\n"
2079 "Connection: keep-alive\r\n"
2080 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2081 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2082 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2083 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2084 "4Ww7b7E=\r\n\r\n"),
2085 };
2086
2087 MockRead data_reads2[] = {
2088 // The origin server responds with a Type 2 message.
2089 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2090 MockRead("WWW-Authenticate: NTLM "
2091 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2092 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2093 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2094 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2095 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2096 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2097 "BtAAAAAAA=\r\n"),
2098 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362099 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292100 MockRead("You are not authorized to view this page\r\n"),
2101
2102 // Wrong password.
2103 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292104 MockRead("WWW-Authenticate: NTLM\r\n"),
2105 MockRead("Connection: close\r\n"),
2106 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362107 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292108 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422109 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292110 };
2111
2112 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222113 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292114 // request we should be issuing -- the final header line contains a Type
2115 // 1 message.
2116 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2117 "Host: 172.22.68.17\r\n"
2118 "Connection: keep-alive\r\n"
2119 "Authorization: NTLM "
2120 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2121
2122 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2123 // (the credentials for the origin server). The second request continues
2124 // on the same connection.
2125 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2126 "Host: 172.22.68.17\r\n"
2127 "Connection: keep-alive\r\n"
2128 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2129 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2130 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2131 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2132 "+4MUm7c=\r\n\r\n"),
2133 };
2134
2135 MockRead data_reads3[] = {
2136 // The origin server responds with a Type 2 message.
2137 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2138 MockRead("WWW-Authenticate: NTLM "
2139 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2140 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2141 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2142 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2143 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2144 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2145 "BtAAAAAAA=\r\n"),
2146 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362147 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292148 MockRead("You are not authorized to view this page\r\n"),
2149
2150 // Lastly we get the desired content.
2151 MockRead("HTTP/1.1 200 OK\r\n"),
2152 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2153 MockRead("Content-Length: 13\r\n\r\n"),
2154 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422155 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292156 };
2157
[email protected]31a2bfe2010-02-09 08:03:392158 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2159 data_writes1, arraysize(data_writes1));
2160 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2161 data_writes2, arraysize(data_writes2));
2162 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2163 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592164 session_deps.socket_factory.AddSocketDataProvider(&data1);
2165 session_deps.socket_factory.AddSocketDataProvider(&data2);
2166 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292167
2168 TestCompletionCallback callback1;
2169
[email protected]5a1d7ca2010-04-28 20:12:272170 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422171 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292172
2173 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422174 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292175
[email protected]0757e7702009-03-27 04:00:222176 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292177 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442178 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422179 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292180 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422181 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222182 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292183
[email protected]1c773ea12009-04-28 19:58:422184 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292185 EXPECT_FALSE(response == NULL);
2186
2187 // The password prompt info should have been set in response->auth_challenge.
2188 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2189
[email protected]71e4573a2009-05-21 22:03:002190 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292191 EXPECT_EQ(L"", response->auth_challenge->realm);
2192 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2193
2194 TestCompletionCallback callback3;
2195
[email protected]0757e7702009-03-27 04:00:222196 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:442197 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:422198 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292199
2200 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422201 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292202
[email protected]0757e7702009-03-27 04:00:222203 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2204 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:442205 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422206 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222207 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422208 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222209 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2210
2211 response = trans->GetResponseInfo();
2212 EXPECT_FALSE(response == NULL);
2213
2214 // The password prompt info should have been set in response->auth_challenge.
2215 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2216
[email protected]71e4573a2009-05-21 22:03:002217 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222218 EXPECT_EQ(L"", response->auth_challenge->realm);
2219 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2220
2221 TestCompletionCallback callback5;
2222
2223 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:442224 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:422225 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222226
2227 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422228 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222229
[email protected]385a4672009-03-11 22:21:292230 response = trans->GetResponseInfo();
2231 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2232 EXPECT_EQ(13, response->headers->GetContentLength());
2233}
[email protected]ea9dc9a2009-09-05 00:43:322234#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292235
[email protected]4ddaf2502008-10-23 18:26:192236// Test reading a server response which has only headers, and no body.
2237// After some maximum number of bytes is consumed, the transaction should
2238// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2239TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592240 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402241 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432242 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192243
[email protected]1c773ea12009-04-28 19:58:422244 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192245 request.method = "GET";
2246 request.url = GURL("http://www.google.com/");
2247 request.load_flags = 0;
2248
[email protected]b75b7b2f2009-10-06 00:54:532249 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432250 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532251 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192252
2253 MockRead data_reads[] = {
2254 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432255 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192256 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422257 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192258 };
[email protected]31a2bfe2010-02-09 08:03:392259 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592260 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192261
2262 TestCompletionCallback callback;
2263
[email protected]5a1d7ca2010-04-28 20:12:272264 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422265 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192266
2267 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422268 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192269
[email protected]1c773ea12009-04-28 19:58:422270 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192271 EXPECT_TRUE(response == NULL);
2272}
[email protected]f4e426b2008-11-05 00:24:492273
2274// Make sure that we don't try to reuse a TCPClientSocket when failing to
2275// establish tunnel.
2276// http://code.google.com/p/chromium/issues/detail?id=3772
2277TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2278 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592279 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012280
[email protected]228ff742009-06-05 01:19:592281 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492282
[email protected]5695b8c2009-09-30 21:36:432283 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492284
[email protected]1c773ea12009-04-28 19:58:422285 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492286 request.method = "GET";
2287 request.url = GURL("https://www.google.com/");
2288 request.load_flags = 0;
2289
2290 // Since we have proxy, should try to establish tunnel.
2291 MockWrite data_writes1[] = {
2292 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452293 "Host: www.google.com\r\n"
2294 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492295 };
2296
[email protected]77848d12008-11-14 00:00:222297 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492298 // connection. Usually a proxy would return 501 (not implemented),
2299 // or 200 (tunnel established).
2300 MockRead data_reads1[] = {
2301 MockRead("HTTP/1.1 404 Not Found\r\n"),
2302 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422303 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492304 };
2305
[email protected]31a2bfe2010-02-09 08:03:392306 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2307 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592308 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492309
2310 TestCompletionCallback callback1;
2311
[email protected]5a1d7ca2010-04-28 20:12:272312 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422313 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492314
2315 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422316 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492317
[email protected]1c773ea12009-04-28 19:58:422318 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082319 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492320
[email protected]b4404c02009-04-10 16:38:522321 // Empty the current queue. This is necessary because idle sockets are
2322 // added to the connection pool asynchronously with a PostTask.
2323 MessageLoop::current()->RunAllPending();
2324
[email protected]f4e426b2008-11-05 00:24:492325 // We now check to make sure the TCPClientSocket was not added back to
2326 // the pool.
[email protected]a937a06d2009-08-19 21:19:242327 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492328 trans.reset();
[email protected]b4404c02009-04-10 16:38:522329 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492330 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242331 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492332}
[email protected]372d34a2008-11-05 21:30:512333
[email protected]1b157c02009-04-21 01:55:402334// Make sure that we recycle a socket after reading all of the response body.
2335TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592336 SessionDependencies session_deps;
2337 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402338
[email protected]5695b8c2009-09-30 21:36:432339 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402340
[email protected]1c773ea12009-04-28 19:58:422341 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402342 request.method = "GET";
2343 request.url = GURL("http://www.google.com/");
2344 request.load_flags = 0;
2345
2346 MockRead data_reads[] = {
2347 // A part of the response body is received with the response headers.
2348 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2349 // The rest of the response body is received in two parts.
2350 MockRead("lo"),
2351 MockRead(" world"),
2352 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422353 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402354 };
2355
[email protected]31a2bfe2010-02-09 08:03:392356 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592357 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402358
2359 TestCompletionCallback callback;
2360
[email protected]5a1d7ca2010-04-28 20:12:272361 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422362 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402363
2364 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422365 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402366
[email protected]1c773ea12009-04-28 19:58:422367 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402368 EXPECT_TRUE(response != NULL);
2369
2370 EXPECT_TRUE(response->headers != NULL);
2371 std::string status_line = response->headers->GetStatusLine();
2372 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2373
[email protected]a937a06d2009-08-19 21:19:242374 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402375
2376 std::string response_data;
2377 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422378 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402379 EXPECT_EQ("hello world", response_data);
2380
2381 // Empty the current queue. This is necessary because idle sockets are
2382 // added to the connection pool asynchronously with a PostTask.
2383 MessageLoop::current()->RunAllPending();
2384
2385 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242386 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402387}
2388
[email protected]b4404c02009-04-10 16:38:522389// Make sure that we recycle a socket after a zero-length response.
2390// http://crbug.com/9880
2391TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592392 SessionDependencies session_deps;
2393 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522394
[email protected]5695b8c2009-09-30 21:36:432395 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522396
[email protected]1c773ea12009-04-28 19:58:422397 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522398 request.method = "GET";
2399 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2400 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2401 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2402 "rt=prt.2642,ol.2649,xjs.2951");
2403 request.load_flags = 0;
2404
2405 MockRead data_reads[] = {
2406 MockRead("HTTP/1.1 204 No Content\r\n"
2407 "Content-Length: 0\r\n"
2408 "Content-Type: text/html\r\n\r\n"),
2409 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422410 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522411 };
2412
[email protected]31a2bfe2010-02-09 08:03:392413 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592414 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522415
2416 TestCompletionCallback callback;
2417
[email protected]5a1d7ca2010-04-28 20:12:272418 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422419 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522420
2421 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422422 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522423
[email protected]1c773ea12009-04-28 19:58:422424 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522425 EXPECT_TRUE(response != NULL);
2426
2427 EXPECT_TRUE(response->headers != NULL);
2428 std::string status_line = response->headers->GetStatusLine();
2429 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2430
[email protected]a937a06d2009-08-19 21:19:242431 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522432
2433 std::string response_data;
2434 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422435 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522436 EXPECT_EQ("", response_data);
2437
2438 // Empty the current queue. This is necessary because idle sockets are
2439 // added to the connection pool asynchronously with a PostTask.
2440 MessageLoop::current()->RunAllPending();
2441
2442 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242443 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522444}
2445
[email protected]372d34a2008-11-05 21:30:512446TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422447 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512448 // Transaction 1: a GET request that succeeds. The socket is recycled
2449 // after use.
2450 request[0].method = "GET";
2451 request[0].url = GURL("http://www.google.com/");
2452 request[0].load_flags = 0;
2453 // Transaction 2: a POST request. Reuses the socket kept alive from
2454 // transaction 1. The first attempts fails when writing the POST data.
2455 // This causes the transaction to retry with a new socket. The second
2456 // attempt succeeds.
2457 request[1].method = "POST";
2458 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422459 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512460 request[1].upload_data->AppendBytes("foo", 3);
2461 request[1].load_flags = 0;
2462
[email protected]228ff742009-06-05 01:19:592463 SessionDependencies session_deps;
2464 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512465
2466 // The first socket is used for transaction 1 and the first attempt of
2467 // transaction 2.
2468
2469 // The response of transaction 1.
2470 MockRead data_reads1[] = {
2471 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2472 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422473 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512474 };
2475 // The mock write results of transaction 1 and the first attempt of
2476 // transaction 2.
2477 MockWrite data_writes1[] = {
2478 MockWrite(false, 64), // GET
2479 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422480 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512481 };
[email protected]31a2bfe2010-02-09 08:03:392482 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2483 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512484
2485 // The second socket is used for the second attempt of transaction 2.
2486
2487 // The response of transaction 2.
2488 MockRead data_reads2[] = {
2489 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2490 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422491 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512492 };
2493 // The mock write results of the second attempt of transaction 2.
2494 MockWrite data_writes2[] = {
2495 MockWrite(false, 93), // POST
2496 MockWrite(false, 3), // POST data
2497 };
[email protected]31a2bfe2010-02-09 08:03:392498 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2499 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512500
[email protected]5ecc992a42009-11-11 01:41:592501 session_deps.socket_factory.AddSocketDataProvider(&data1);
2502 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512503
2504 const char* kExpectedResponseData[] = {
2505 "hello world", "welcome"
2506 };
2507
2508 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422509 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432510 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512511
2512 TestCompletionCallback callback;
2513
[email protected]5a1d7ca2010-04-28 20:12:272514 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422515 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512516
2517 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422518 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512519
[email protected]1c773ea12009-04-28 19:58:422520 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512521 EXPECT_TRUE(response != NULL);
2522
2523 EXPECT_TRUE(response->headers != NULL);
2524 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2525
2526 std::string response_data;
2527 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422528 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512529 EXPECT_EQ(kExpectedResponseData[i], response_data);
2530 }
2531}
[email protected]f9ee6b52008-11-08 06:46:232532
2533// Test the request-challenge-retry sequence for basic auth when there is
2534// an identity in the URL. The request should be sent as normal, but when
2535// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322536TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592537 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402538 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432539 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232540
[email protected]1c773ea12009-04-28 19:58:422541 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232542 request.method = "GET";
2543 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292544 request.url = GURL("http://foo:b@[email protected]/");
2545
2546 // The password contains an escaped character -- for this test to pass it
2547 // will need to be unescaped by HttpNetworkTransaction.
2548 EXPECT_EQ("b%40r", request.url.password());
2549
[email protected]ea9dc9a2009-09-05 00:43:322550 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232551
2552 MockWrite data_writes1[] = {
2553 MockWrite("GET / HTTP/1.1\r\n"
2554 "Host: www.google.com\r\n"
2555 "Connection: keep-alive\r\n\r\n"),
2556 };
2557
2558 MockRead data_reads1[] = {
2559 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2560 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2561 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422562 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232563 };
2564
2565 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322566 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232567 MockWrite data_writes2[] = {
2568 MockWrite("GET / HTTP/1.1\r\n"
2569 "Host: www.google.com\r\n"
2570 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292571 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232572 };
2573
2574 MockRead data_reads2[] = {
2575 MockRead("HTTP/1.0 200 OK\r\n"),
2576 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422577 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232578 };
2579
[email protected]31a2bfe2010-02-09 08:03:392580 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2581 data_writes1, arraysize(data_writes1));
2582 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2583 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592584 session_deps.socket_factory.AddSocketDataProvider(&data1);
2585 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232586
2587 TestCompletionCallback callback1;
2588
[email protected]5a1d7ca2010-04-28 20:12:272589 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422590 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232591
2592 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422593 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232594
[email protected]0757e7702009-03-27 04:00:222595 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2596 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442597 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422598 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222599 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422600 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222601 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2602
[email protected]1c773ea12009-04-28 19:58:422603 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232604 EXPECT_FALSE(response == NULL);
2605
2606 // There is no challenge info, since the identity in URL worked.
2607 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2608
2609 EXPECT_EQ(100, response->headers->GetContentLength());
2610
2611 // Empty the current queue.
2612 MessageLoop::current()->RunAllPending();
2613}
2614
[email protected]ea9dc9a2009-09-05 00:43:322615// Test the request-challenge-retry sequence for basic auth when there is
2616// an incorrect identity in the URL. The identity from the URL should be used
2617// only once.
2618TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2619 SessionDependencies session_deps;
2620 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432621 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322622
2623 HttpRequestInfo request;
2624 request.method = "GET";
2625 // Note: the URL has a username:password in it. The password "baz" is
2626 // wrong (should be "bar").
2627 request.url = GURL("http://foo:[email protected]/");
2628
2629 request.load_flags = LOAD_NORMAL;
2630
2631 MockWrite data_writes1[] = {
2632 MockWrite("GET / HTTP/1.1\r\n"
2633 "Host: www.google.com\r\n"
2634 "Connection: keep-alive\r\n\r\n"),
2635 };
2636
2637 MockRead data_reads1[] = {
2638 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2639 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2640 MockRead("Content-Length: 10\r\n\r\n"),
2641 MockRead(false, ERR_FAILED),
2642 };
2643
2644 // After the challenge above, the transaction will be restarted using the
2645 // identity from the url (foo, baz) to answer the challenge.
2646 MockWrite data_writes2[] = {
2647 MockWrite("GET / HTTP/1.1\r\n"
2648 "Host: www.google.com\r\n"
2649 "Connection: keep-alive\r\n"
2650 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2651 };
2652
2653 MockRead data_reads2[] = {
2654 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2655 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2656 MockRead("Content-Length: 10\r\n\r\n"),
2657 MockRead(false, ERR_FAILED),
2658 };
2659
2660 // After the challenge above, the transaction will be restarted using the
2661 // identity supplied by the user (foo, bar) to answer the challenge.
2662 MockWrite data_writes3[] = {
2663 MockWrite("GET / HTTP/1.1\r\n"
2664 "Host: www.google.com\r\n"
2665 "Connection: keep-alive\r\n"
2666 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2667 };
2668
2669 MockRead data_reads3[] = {
2670 MockRead("HTTP/1.0 200 OK\r\n"),
2671 MockRead("Content-Length: 100\r\n\r\n"),
2672 MockRead(false, OK),
2673 };
2674
[email protected]31a2bfe2010-02-09 08:03:392675 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2676 data_writes1, arraysize(data_writes1));
2677 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2678 data_writes2, arraysize(data_writes2));
2679 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2680 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592681 session_deps.socket_factory.AddSocketDataProvider(&data1);
2682 session_deps.socket_factory.AddSocketDataProvider(&data2);
2683 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322684
2685 TestCompletionCallback callback1;
2686
[email protected]5a1d7ca2010-04-28 20:12:272687 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322688 EXPECT_EQ(ERR_IO_PENDING, rv);
2689
2690 rv = callback1.WaitForResult();
2691 EXPECT_EQ(OK, rv);
2692
2693 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2694 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442695 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:322696 EXPECT_EQ(ERR_IO_PENDING, rv);
2697 rv = callback2.WaitForResult();
2698 EXPECT_EQ(OK, rv);
2699 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2700
2701 const HttpResponseInfo* response = trans->GetResponseInfo();
2702 EXPECT_FALSE(response == NULL);
2703 // The password prompt info should have been set in response->auth_challenge.
2704 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2705
2706 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2707 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2708 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2709
2710 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:442711 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:322712 EXPECT_EQ(ERR_IO_PENDING, rv);
2713 rv = callback3.WaitForResult();
2714 EXPECT_EQ(OK, rv);
2715 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2716
2717 response = trans->GetResponseInfo();
2718 EXPECT_FALSE(response == NULL);
2719
2720 // There is no challenge info, since the identity worked.
2721 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2722
2723 EXPECT_EQ(100, response->headers->GetContentLength());
2724
2725 // Empty the current queue.
2726 MessageLoop::current()->RunAllPending();
2727}
2728
[email protected]f9ee6b52008-11-08 06:46:232729// Test that previously tried username/passwords for a realm get re-used.
2730TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592731 SessionDependencies session_deps;
2732 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232733
2734 // Transaction 1: authenticate (foo, bar) on MyRealm1
2735 {
[email protected]5695b8c2009-09-30 21:36:432736 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232737
[email protected]1c773ea12009-04-28 19:58:422738 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232739 request.method = "GET";
2740 request.url = GURL("http://www.google.com/x/y/z");
2741 request.load_flags = 0;
2742
2743 MockWrite data_writes1[] = {
2744 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2745 "Host: www.google.com\r\n"
2746 "Connection: keep-alive\r\n\r\n"),
2747 };
2748
2749 MockRead data_reads1[] = {
2750 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2751 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2752 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422753 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232754 };
2755
2756 // Resend with authorization (username=foo, password=bar)
2757 MockWrite data_writes2[] = {
2758 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2759 "Host: www.google.com\r\n"
2760 "Connection: keep-alive\r\n"
2761 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2762 };
2763
2764 // Sever accepts the authorization.
2765 MockRead data_reads2[] = {
2766 MockRead("HTTP/1.0 200 OK\r\n"),
2767 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422768 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232769 };
2770
[email protected]31a2bfe2010-02-09 08:03:392771 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2772 data_writes1, arraysize(data_writes1));
2773 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2774 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592775 session_deps.socket_factory.AddSocketDataProvider(&data1);
2776 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232777
2778 TestCompletionCallback callback1;
2779
[email protected]5a1d7ca2010-04-28 20:12:272780 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422781 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232782
2783 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422784 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232785
[email protected]1c773ea12009-04-28 19:58:422786 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232787 EXPECT_FALSE(response == NULL);
2788
2789 // The password prompt info should have been set in
2790 // response->auth_challenge.
2791 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2792
[email protected]71e4573a2009-05-21 22:03:002793 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232794 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2795 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2796
2797 TestCompletionCallback callback2;
2798
[email protected]13c8a092010-07-29 06:15:442799 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422800 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232801
2802 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422803 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232804
2805 response = trans->GetResponseInfo();
2806 EXPECT_FALSE(response == NULL);
2807 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2808 EXPECT_EQ(100, response->headers->GetContentLength());
2809 }
2810
2811 // ------------------------------------------------------------------------
2812
2813 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2814 {
[email protected]5695b8c2009-09-30 21:36:432815 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232816
[email protected]1c773ea12009-04-28 19:58:422817 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232818 request.method = "GET";
2819 // Note that Transaction 1 was at /x/y/z, so this is in the same
2820 // protection space as MyRealm1.
2821 request.url = GURL("http://www.google.com/x/y/a/b");
2822 request.load_flags = 0;
2823
2824 MockWrite data_writes1[] = {
2825 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2826 "Host: www.google.com\r\n"
2827 "Connection: keep-alive\r\n"
2828 // Send preemptive authorization for MyRealm1
2829 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2830 };
2831
2832 // The server didn't like the preemptive authorization, and
2833 // challenges us for a different realm (MyRealm2).
2834 MockRead data_reads1[] = {
2835 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2836 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2837 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422838 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232839 };
2840
2841 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2842 MockWrite data_writes2[] = {
2843 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2844 "Host: www.google.com\r\n"
2845 "Connection: keep-alive\r\n"
2846 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2847 };
2848
2849 // Sever accepts the authorization.
2850 MockRead data_reads2[] = {
2851 MockRead("HTTP/1.0 200 OK\r\n"),
2852 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422853 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232854 };
2855
[email protected]31a2bfe2010-02-09 08:03:392856 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2857 data_writes1, arraysize(data_writes1));
2858 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2859 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592860 session_deps.socket_factory.AddSocketDataProvider(&data1);
2861 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232862
2863 TestCompletionCallback callback1;
2864
[email protected]5a1d7ca2010-04-28 20:12:272865 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422866 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232867
2868 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422869 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232870
[email protected]1c773ea12009-04-28 19:58:422871 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232872 EXPECT_FALSE(response == NULL);
2873
2874 // The password prompt info should have been set in
2875 // response->auth_challenge.
2876 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2877
[email protected]71e4573a2009-05-21 22:03:002878 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232879 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2880 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2881
2882 TestCompletionCallback callback2;
2883
[email protected]13c8a092010-07-29 06:15:442884 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:422885 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232886
2887 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422888 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232889
2890 response = trans->GetResponseInfo();
2891 EXPECT_FALSE(response == NULL);
2892 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2893 EXPECT_EQ(100, response->headers->GetContentLength());
2894 }
2895
2896 // ------------------------------------------------------------------------
2897
2898 // Transaction 3: Resend a request in MyRealm's protection space --
2899 // succeed with preemptive authorization.
2900 {
[email protected]5695b8c2009-09-30 21:36:432901 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232902
[email protected]1c773ea12009-04-28 19:58:422903 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232904 request.method = "GET";
2905 request.url = GURL("http://www.google.com/x/y/z2");
2906 request.load_flags = 0;
2907
2908 MockWrite data_writes1[] = {
2909 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2910 "Host: www.google.com\r\n"
2911 "Connection: keep-alive\r\n"
2912 // The authorization for MyRealm1 gets sent preemptively
2913 // (since the url is in the same protection space)
2914 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2915 };
2916
2917 // Sever accepts the preemptive authorization
2918 MockRead data_reads1[] = {
2919 MockRead("HTTP/1.0 200 OK\r\n"),
2920 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422921 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232922 };
2923
[email protected]31a2bfe2010-02-09 08:03:392924 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2925 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592926 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232927
2928 TestCompletionCallback callback1;
2929
[email protected]5a1d7ca2010-04-28 20:12:272930 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422931 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232932
2933 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422934 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232935
[email protected]1c773ea12009-04-28 19:58:422936 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232937 EXPECT_FALSE(response == NULL);
2938
2939 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2940 EXPECT_EQ(100, response->headers->GetContentLength());
2941 }
2942
2943 // ------------------------------------------------------------------------
2944
2945 // Transaction 4: request another URL in MyRealm (however the
2946 // url is not known to belong to the protection space, so no pre-auth).
2947 {
[email protected]5695b8c2009-09-30 21:36:432948 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232949
[email protected]1c773ea12009-04-28 19:58:422950 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232951 request.method = "GET";
2952 request.url = GURL("http://www.google.com/x/1");
2953 request.load_flags = 0;
2954
2955 MockWrite data_writes1[] = {
2956 MockWrite("GET /x/1 HTTP/1.1\r\n"
2957 "Host: www.google.com\r\n"
2958 "Connection: keep-alive\r\n\r\n"),
2959 };
2960
2961 MockRead data_reads1[] = {
2962 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2963 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2964 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422965 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232966 };
2967
2968 // Resend with authorization from MyRealm's cache.
2969 MockWrite data_writes2[] = {
2970 MockWrite("GET /x/1 HTTP/1.1\r\n"
2971 "Host: www.google.com\r\n"
2972 "Connection: keep-alive\r\n"
2973 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2974 };
2975
2976 // Sever accepts the authorization.
2977 MockRead data_reads2[] = {
2978 MockRead("HTTP/1.0 200 OK\r\n"),
2979 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422980 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232981 };
2982
[email protected]31a2bfe2010-02-09 08:03:392983 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2984 data_writes1, arraysize(data_writes1));
2985 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2986 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592987 session_deps.socket_factory.AddSocketDataProvider(&data1);
2988 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232989
2990 TestCompletionCallback callback1;
2991
[email protected]5a1d7ca2010-04-28 20:12:272992 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422993 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232994
2995 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422996 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232997
[email protected]0757e7702009-03-27 04:00:222998 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2999 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443000 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423001 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223002 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423003 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223004 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3005
[email protected]1c773ea12009-04-28 19:58:423006 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233007 EXPECT_FALSE(response == NULL);
3008 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3009 EXPECT_EQ(100, response->headers->GetContentLength());
3010 }
3011
3012 // ------------------------------------------------------------------------
3013
3014 // Transaction 5: request a URL in MyRealm, but the server rejects the
3015 // cached identity. Should invalidate and re-prompt.
3016 {
[email protected]5695b8c2009-09-30 21:36:433017 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233018
[email protected]1c773ea12009-04-28 19:58:423019 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233020 request.method = "GET";
3021 request.url = GURL("http://www.google.com/p/q/t");
3022 request.load_flags = 0;
3023
3024 MockWrite data_writes1[] = {
3025 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3026 "Host: www.google.com\r\n"
3027 "Connection: keep-alive\r\n\r\n"),
3028 };
3029
3030 MockRead data_reads1[] = {
3031 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3032 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3033 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423034 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233035 };
3036
3037 // Resend with authorization from cache for MyRealm.
3038 MockWrite data_writes2[] = {
3039 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3040 "Host: www.google.com\r\n"
3041 "Connection: keep-alive\r\n"
3042 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3043 };
3044
3045 // Sever rejects the authorization.
3046 MockRead data_reads2[] = {
3047 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3048 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3049 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423050 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233051 };
3052
3053 // At this point we should prompt for new credentials for MyRealm.
3054 // Restart with username=foo3, password=foo4.
3055 MockWrite data_writes3[] = {
3056 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3057 "Host: www.google.com\r\n"
3058 "Connection: keep-alive\r\n"
3059 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3060 };
3061
3062 // Sever accepts the authorization.
3063 MockRead data_reads3[] = {
3064 MockRead("HTTP/1.0 200 OK\r\n"),
3065 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423066 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233067 };
3068
[email protected]31a2bfe2010-02-09 08:03:393069 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3070 data_writes1, arraysize(data_writes1));
3071 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3072 data_writes2, arraysize(data_writes2));
3073 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3074 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593075 session_deps.socket_factory.AddSocketDataProvider(&data1);
3076 session_deps.socket_factory.AddSocketDataProvider(&data2);
3077 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233078
3079 TestCompletionCallback callback1;
3080
[email protected]5a1d7ca2010-04-28 20:12:273081 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423082 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233083
3084 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423085 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233086
[email protected]0757e7702009-03-27 04:00:223087 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3088 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443089 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423090 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223091 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423092 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223093 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3094
[email protected]1c773ea12009-04-28 19:58:423095 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233096 EXPECT_FALSE(response == NULL);
3097
3098 // The password prompt info should have been set in
3099 // response->auth_challenge.
3100 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3101
[email protected]71e4573a2009-05-21 22:03:003102 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233103 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3104 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3105
[email protected]0757e7702009-03-27 04:00:223106 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233107
[email protected]13c8a092010-07-29 06:15:443108 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:423109 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233110
[email protected]0757e7702009-03-27 04:00:223111 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423112 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233113
3114 response = trans->GetResponseInfo();
3115 EXPECT_FALSE(response == NULL);
3116 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3117 EXPECT_EQ(100, response->headers->GetContentLength());
3118 }
3119}
[email protected]89ceba9a2009-03-21 03:46:063120
[email protected]3c32c5f2010-05-18 15:18:123121// Tests that nonce count increments when multiple auth attempts
3122// are started with the same nonce.
3123TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3124 SessionDependencies session_deps;
3125 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3126 HttpAuthHandlerDigest::SetFixedCnonce(true);
3127
3128 // Transaction 1: authenticate (foo, bar) on MyRealm1
3129 {
3130 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3131
3132 HttpRequestInfo request;
3133 request.method = "GET";
3134 request.url = GURL("http://www.google.com/x/y/z");
3135 request.load_flags = 0;
3136
3137 MockWrite data_writes1[] = {
3138 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3139 "Host: www.google.com\r\n"
3140 "Connection: keep-alive\r\n\r\n"),
3141 };
3142
3143 MockRead data_reads1[] = {
3144 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3145 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3146 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3147 MockRead(false, OK),
3148 };
3149
3150 // Resend with authorization (username=foo, password=bar)
3151 MockWrite data_writes2[] = {
3152 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3153 "Host: www.google.com\r\n"
3154 "Connection: keep-alive\r\n"
3155 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3156 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3157 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3158 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3159 };
3160
3161 // Sever accepts the authorization.
3162 MockRead data_reads2[] = {
3163 MockRead("HTTP/1.0 200 OK\r\n"),
3164 MockRead(false, OK),
3165 };
3166
3167 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3168 data_writes1, arraysize(data_writes1));
3169 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3170 data_writes2, arraysize(data_writes2));
3171 session_deps.socket_factory.AddSocketDataProvider(&data1);
3172 session_deps.socket_factory.AddSocketDataProvider(&data2);
3173
3174 TestCompletionCallback callback1;
3175
3176 int rv = trans->Start(&request, &callback1, BoundNetLog());
3177 EXPECT_EQ(ERR_IO_PENDING, rv);
3178
3179 rv = callback1.WaitForResult();
3180 EXPECT_EQ(OK, rv);
3181
3182 const HttpResponseInfo* response = trans->GetResponseInfo();
3183 ASSERT_FALSE(response == NULL);
3184
3185 // The password prompt info should have been set in
3186 // response->auth_challenge.
3187 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3188
3189 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3190 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3191 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3192
3193 TestCompletionCallback callback2;
3194
[email protected]13c8a092010-07-29 06:15:443195 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:123196 EXPECT_EQ(ERR_IO_PENDING, rv);
3197
3198 rv = callback2.WaitForResult();
3199 EXPECT_EQ(OK, rv);
3200
3201 response = trans->GetResponseInfo();
3202 ASSERT_FALSE(response == NULL);
3203 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3204 }
3205
3206 // ------------------------------------------------------------------------
3207
3208 // Transaction 2: Request another resource in digestive's protection space.
3209 // This will preemptively add an Authorization header which should have an
3210 // "nc" value of 2 (as compared to 1 in the first use.
3211 {
3212 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3213
3214 HttpRequestInfo request;
3215 request.method = "GET";
3216 // Note that Transaction 1 was at /x/y/z, so this is in the same
3217 // protection space as digest.
3218 request.url = GURL("http://www.google.com/x/y/a/b");
3219 request.load_flags = 0;
3220
3221 MockWrite data_writes1[] = {
3222 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3223 "Host: www.google.com\r\n"
3224 "Connection: keep-alive\r\n"
3225 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3226 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3227 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3228 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3229 };
3230
3231 // Sever accepts the authorization.
3232 MockRead data_reads1[] = {
3233 MockRead("HTTP/1.0 200 OK\r\n"),
3234 MockRead("Content-Length: 100\r\n\r\n"),
3235 MockRead(false, OK),
3236 };
3237
3238 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3239 data_writes1, arraysize(data_writes1));
3240 session_deps.socket_factory.AddSocketDataProvider(&data1);
3241
3242 TestCompletionCallback callback1;
3243
3244 int rv = trans->Start(&request, &callback1, BoundNetLog());
3245 EXPECT_EQ(ERR_IO_PENDING, rv);
3246
3247 rv = callback1.WaitForResult();
3248 EXPECT_EQ(OK, rv);
3249
3250 const HttpResponseInfo* response = trans->GetResponseInfo();
3251 ASSERT_FALSE(response == NULL);
3252 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3253 }
3254}
3255
[email protected]89ceba9a2009-03-21 03:46:063256// Test the ResetStateForRestart() private method.
3257TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3258 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593259 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403260 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433261 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063262
3263 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063264 trans->read_buf_ = new IOBuffer(15);
3265 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573266 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063267
3268 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143269 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573270 response->auth_challenge = new AuthChallengeInfo();
3271 response->ssl_info.cert_status = -15;
3272 response->response_time = base::Time::Now();
3273 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063274
3275 { // Setup state for response_.vary_data
3276 HttpRequestInfo request;
3277 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3278 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573279 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433280 request.extra_headers.SetHeader("Foo", "1");
3281 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573282 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063283 }
3284
3285 // Cause the above state to be reset.
3286 trans->ResetStateForRestart();
3287
3288 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073289 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063290 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573291 EXPECT_EQ(0U, trans->request_headers_.size());
3292 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3293 EXPECT_TRUE(response->headers.get() == NULL);
3294 EXPECT_EQ(false, response->was_cached);
3295 EXPECT_EQ(0, response->ssl_info.cert_status);
3296 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063297}
3298
[email protected]bacff652009-03-31 17:50:333299// Test HTTPS connections to a site with a bad certificate
3300TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593301 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403302 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433303 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333304
3305 HttpRequestInfo request;
3306 request.method = "GET";
3307 request.url = GURL("https://www.google.com/");
3308 request.load_flags = 0;
3309
3310 MockWrite data_writes[] = {
3311 MockWrite("GET / HTTP/1.1\r\n"
3312 "Host: www.google.com\r\n"
3313 "Connection: keep-alive\r\n\r\n"),
3314 };
3315
3316 MockRead data_reads[] = {
3317 MockRead("HTTP/1.0 200 OK\r\n"),
3318 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3319 MockRead("Content-Length: 100\r\n\r\n"),
3320 MockRead(false, OK),
3321 };
3322
[email protected]5ecc992a42009-11-11 01:41:593323 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393324 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3325 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593326 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3327 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333328
[email protected]5ecc992a42009-11-11 01:41:593329 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3330 session_deps.socket_factory.AddSocketDataProvider(&data);
3331 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3332 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333333
3334 TestCompletionCallback callback;
3335
[email protected]5a1d7ca2010-04-28 20:12:273336 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333337 EXPECT_EQ(ERR_IO_PENDING, rv);
3338
3339 rv = callback.WaitForResult();
3340 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3341
3342 rv = trans->RestartIgnoringLastError(&callback);
3343 EXPECT_EQ(ERR_IO_PENDING, rv);
3344
3345 rv = callback.WaitForResult();
3346 EXPECT_EQ(OK, rv);
3347
3348 const HttpResponseInfo* response = trans->GetResponseInfo();
3349
3350 EXPECT_FALSE(response == NULL);
3351 EXPECT_EQ(100, response->headers->GetContentLength());
3352}
3353
3354// Test HTTPS connections to a site with a bad certificate, going through a
3355// proxy
3356TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593357 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333358
3359 HttpRequestInfo request;
3360 request.method = "GET";
3361 request.url = GURL("https://www.google.com/");
3362 request.load_flags = 0;
3363
3364 MockWrite proxy_writes[] = {
3365 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453366 "Host: www.google.com\r\n"
3367 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333368 };
3369
3370 MockRead proxy_reads[] = {
3371 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423372 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333373 };
3374
3375 MockWrite data_writes[] = {
3376 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453377 "Host: www.google.com\r\n"
3378 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333379 MockWrite("GET / HTTP/1.1\r\n"
3380 "Host: www.google.com\r\n"
3381 "Connection: keep-alive\r\n\r\n"),
3382 };
3383
3384 MockRead data_reads[] = {
3385 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3386 MockRead("HTTP/1.0 200 OK\r\n"),
3387 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3388 MockRead("Content-Length: 100\r\n\r\n"),
3389 MockRead(false, OK),
3390 };
3391
[email protected]31a2bfe2010-02-09 08:03:393392 StaticSocketDataProvider ssl_bad_certificate(
3393 proxy_reads, arraysize(proxy_reads),
3394 proxy_writes, arraysize(proxy_writes));
3395 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3396 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593397 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3398 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333399
[email protected]5ecc992a42009-11-11 01:41:593400 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3401 session_deps.socket_factory.AddSocketDataProvider(&data);
3402 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3403 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333404
3405 TestCompletionCallback callback;
3406
3407 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593408 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333409
[email protected]d207a5f2009-06-04 05:28:403410 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433411 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333412
[email protected]5a1d7ca2010-04-28 20:12:273413 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333414 EXPECT_EQ(ERR_IO_PENDING, rv);
3415
3416 rv = callback.WaitForResult();
3417 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3418
3419 rv = trans->RestartIgnoringLastError(&callback);
3420 EXPECT_EQ(ERR_IO_PENDING, rv);
3421
3422 rv = callback.WaitForResult();
3423 EXPECT_EQ(OK, rv);
3424
3425 const HttpResponseInfo* response = trans->GetResponseInfo();
3426
3427 EXPECT_FALSE(response == NULL);
3428 EXPECT_EQ(100, response->headers->GetContentLength());
3429 }
3430}
3431
[email protected]1c773ea12009-04-28 19:58:423432TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593433 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403434 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433435 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423436
3437 HttpRequestInfo request;
3438 request.method = "GET";
3439 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433440 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3441 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423442
3443 MockWrite data_writes[] = {
3444 MockWrite("GET / HTTP/1.1\r\n"
3445 "Host: www.google.com\r\n"
3446 "Connection: keep-alive\r\n"
3447 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3448 };
3449
3450 // Lastly, the server responds with the actual content.
3451 MockRead data_reads[] = {
3452 MockRead("HTTP/1.0 200 OK\r\n"),
3453 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3454 MockRead("Content-Length: 100\r\n\r\n"),
3455 MockRead(false, OK),
3456 };
3457
[email protected]31a2bfe2010-02-09 08:03:393458 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3459 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593460 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423461
3462 TestCompletionCallback callback;
3463
[email protected]5a1d7ca2010-04-28 20:12:273464 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423465 EXPECT_EQ(ERR_IO_PENDING, rv);
3466
3467 rv = callback.WaitForResult();
3468 EXPECT_EQ(OK, rv);
3469}
3470
3471TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593472 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403473 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433474 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423475
3476 HttpRequestInfo request;
3477 request.method = "GET";
3478 request.url = GURL("http://www.google.com/");
3479 request.load_flags = 0;
3480 request.referrer = GURL("http://the.previous.site.com/");
3481
3482 MockWrite data_writes[] = {
3483 MockWrite("GET / HTTP/1.1\r\n"
3484 "Host: www.google.com\r\n"
3485 "Connection: keep-alive\r\n"
3486 "Referer: http://the.previous.site.com/\r\n\r\n"),
3487 };
3488
3489 // Lastly, the server responds with the actual content.
3490 MockRead data_reads[] = {
3491 MockRead("HTTP/1.0 200 OK\r\n"),
3492 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3493 MockRead("Content-Length: 100\r\n\r\n"),
3494 MockRead(false, OK),
3495 };
3496
[email protected]31a2bfe2010-02-09 08:03:393497 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3498 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593499 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423500
3501 TestCompletionCallback callback;
3502
[email protected]5a1d7ca2010-04-28 20:12:273503 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423504 EXPECT_EQ(ERR_IO_PENDING, rv);
3505
3506 rv = callback.WaitForResult();
3507 EXPECT_EQ(OK, rv);
3508}
3509
3510TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593511 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403512 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433513 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423514
3515 HttpRequestInfo request;
3516 request.method = "POST";
3517 request.url = GURL("http://www.google.com/");
3518
3519 MockWrite data_writes[] = {
3520 MockWrite("POST / HTTP/1.1\r\n"
3521 "Host: www.google.com\r\n"
3522 "Connection: keep-alive\r\n"
3523 "Content-Length: 0\r\n\r\n"),
3524 };
3525
3526 // Lastly, the server responds with the actual content.
3527 MockRead data_reads[] = {
3528 MockRead("HTTP/1.0 200 OK\r\n"),
3529 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3530 MockRead("Content-Length: 100\r\n\r\n"),
3531 MockRead(false, OK),
3532 };
3533
[email protected]31a2bfe2010-02-09 08:03:393534 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3535 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593536 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423537
3538 TestCompletionCallback callback;
3539
[email protected]5a1d7ca2010-04-28 20:12:273540 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423541 EXPECT_EQ(ERR_IO_PENDING, rv);
3542
3543 rv = callback.WaitForResult();
3544 EXPECT_EQ(OK, rv);
3545}
3546
3547TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593548 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403549 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433550 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423551
3552 HttpRequestInfo request;
3553 request.method = "PUT";
3554 request.url = GURL("http://www.google.com/");
3555
3556 MockWrite data_writes[] = {
3557 MockWrite("PUT / HTTP/1.1\r\n"
3558 "Host: www.google.com\r\n"
3559 "Connection: keep-alive\r\n"
3560 "Content-Length: 0\r\n\r\n"),
3561 };
3562
3563 // Lastly, the server responds with the actual content.
3564 MockRead data_reads[] = {
3565 MockRead("HTTP/1.0 200 OK\r\n"),
3566 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3567 MockRead("Content-Length: 100\r\n\r\n"),
3568 MockRead(false, OK),
3569 };
3570
[email protected]31a2bfe2010-02-09 08:03:393571 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3572 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593573 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423574
3575 TestCompletionCallback callback;
3576
[email protected]5a1d7ca2010-04-28 20:12:273577 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423578 EXPECT_EQ(ERR_IO_PENDING, rv);
3579
3580 rv = callback.WaitForResult();
3581 EXPECT_EQ(OK, rv);
3582}
3583
3584TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593585 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403586 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433587 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423588
3589 HttpRequestInfo request;
3590 request.method = "HEAD";
3591 request.url = GURL("http://www.google.com/");
3592
3593 MockWrite data_writes[] = {
3594 MockWrite("HEAD / HTTP/1.1\r\n"
3595 "Host: www.google.com\r\n"
3596 "Connection: keep-alive\r\n"
3597 "Content-Length: 0\r\n\r\n"),
3598 };
3599
3600 // Lastly, the server responds with the actual content.
3601 MockRead data_reads[] = {
3602 MockRead("HTTP/1.0 200 OK\r\n"),
3603 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3604 MockRead("Content-Length: 100\r\n\r\n"),
3605 MockRead(false, OK),
3606 };
3607
[email protected]31a2bfe2010-02-09 08:03:393608 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3609 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593610 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423611
3612 TestCompletionCallback callback;
3613
[email protected]5a1d7ca2010-04-28 20:12:273614 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423615 EXPECT_EQ(ERR_IO_PENDING, rv);
3616
3617 rv = callback.WaitForResult();
3618 EXPECT_EQ(OK, rv);
3619}
3620
3621TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593622 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403623 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433624 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423625
3626 HttpRequestInfo request;
3627 request.method = "GET";
3628 request.url = GURL("http://www.google.com/");
3629 request.load_flags = LOAD_BYPASS_CACHE;
3630
3631 MockWrite data_writes[] = {
3632 MockWrite("GET / HTTP/1.1\r\n"
3633 "Host: www.google.com\r\n"
3634 "Connection: keep-alive\r\n"
3635 "Pragma: no-cache\r\n"
3636 "Cache-Control: no-cache\r\n\r\n"),
3637 };
3638
3639 // Lastly, the server responds with the actual content.
3640 MockRead data_reads[] = {
3641 MockRead("HTTP/1.0 200 OK\r\n"),
3642 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3643 MockRead("Content-Length: 100\r\n\r\n"),
3644 MockRead(false, OK),
3645 };
3646
[email protected]31a2bfe2010-02-09 08:03:393647 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3648 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593649 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423650
3651 TestCompletionCallback callback;
3652
[email protected]5a1d7ca2010-04-28 20:12:273653 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423654 EXPECT_EQ(ERR_IO_PENDING, rv);
3655
3656 rv = callback.WaitForResult();
3657 EXPECT_EQ(OK, rv);
3658}
3659
3660TEST_F(HttpNetworkTransactionTest,
3661 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593662 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403663 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433664 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423665
3666 HttpRequestInfo request;
3667 request.method = "GET";
3668 request.url = GURL("http://www.google.com/");
3669 request.load_flags = LOAD_VALIDATE_CACHE;
3670
3671 MockWrite data_writes[] = {
3672 MockWrite("GET / HTTP/1.1\r\n"
3673 "Host: www.google.com\r\n"
3674 "Connection: keep-alive\r\n"
3675 "Cache-Control: max-age=0\r\n\r\n"),
3676 };
3677
3678 // Lastly, the server responds with the actual content.
3679 MockRead data_reads[] = {
3680 MockRead("HTTP/1.0 200 OK\r\n"),
3681 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3682 MockRead("Content-Length: 100\r\n\r\n"),
3683 MockRead(false, OK),
3684 };
3685
[email protected]31a2bfe2010-02-09 08:03:393686 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3687 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593688 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423689
3690 TestCompletionCallback callback;
3691
[email protected]5a1d7ca2010-04-28 20:12:273692 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423693 EXPECT_EQ(ERR_IO_PENDING, rv);
3694
3695 rv = callback.WaitForResult();
3696 EXPECT_EQ(OK, rv);
3697}
3698
3699TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593700 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403701 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433702 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423703
3704 HttpRequestInfo request;
3705 request.method = "GET";
3706 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433707 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423708
3709 MockWrite data_writes[] = {
3710 MockWrite("GET / HTTP/1.1\r\n"
3711 "Host: www.google.com\r\n"
3712 "Connection: keep-alive\r\n"
3713 "FooHeader: Bar\r\n\r\n"),
3714 };
3715
3716 // Lastly, the server responds with the actual content.
3717 MockRead data_reads[] = {
3718 MockRead("HTTP/1.0 200 OK\r\n"),
3719 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3720 MockRead("Content-Length: 100\r\n\r\n"),
3721 MockRead(false, OK),
3722 };
3723
[email protected]31a2bfe2010-02-09 08:03:393724 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3725 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593726 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423727
3728 TestCompletionCallback callback;
3729
[email protected]5a1d7ca2010-04-28 20:12:273730 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423731 EXPECT_EQ(ERR_IO_PENDING, rv);
3732
3733 rv = callback.WaitForResult();
3734 EXPECT_EQ(OK, rv);
3735}
3736
[email protected]270c6412010-03-29 22:02:473737TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3738 SessionDependencies session_deps;
3739 scoped_ptr<HttpTransaction> trans(
3740 new HttpNetworkTransaction(CreateSession(&session_deps)));
3741
3742 HttpRequestInfo request;
3743 request.method = "GET";
3744 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433745 request.extra_headers.SetHeader("referer", "www.foo.com");
3746 request.extra_headers.SetHeader("hEllo", "Kitty");
3747 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473748
3749 MockWrite data_writes[] = {
3750 MockWrite("GET / HTTP/1.1\r\n"
3751 "Host: www.google.com\r\n"
3752 "Connection: keep-alive\r\n"
3753 "hEllo: Kitty\r\n"
3754 "FoO: bar\r\n\r\n"),
3755 };
3756
3757 // Lastly, the server responds with the actual content.
3758 MockRead data_reads[] = {
3759 MockRead("HTTP/1.0 200 OK\r\n"),
3760 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3761 MockRead("Content-Length: 100\r\n\r\n"),
3762 MockRead(false, OK),
3763 };
3764
3765 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3766 data_writes, arraysize(data_writes));
3767 session_deps.socket_factory.AddSocketDataProvider(&data);
3768
3769 TestCompletionCallback callback;
3770
[email protected]5a1d7ca2010-04-28 20:12:273771 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473772 EXPECT_EQ(ERR_IO_PENDING, rv);
3773
3774 rv = callback.WaitForResult();
3775 EXPECT_EQ(OK, rv);
3776}
3777
[email protected]3cd17242009-06-23 02:59:023778TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093779 SessionDependencies session_deps(
3780 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023781
3782 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433783 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023784
3785 HttpRequestInfo request;
3786 request.method = "GET";
3787 request.url = GURL("http://www.google.com/");
3788 request.load_flags = 0;
3789
3790 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3791 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3792
3793 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353794 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023795 MockWrite("GET / HTTP/1.1\r\n"
3796 "Host: www.google.com\r\n"
3797 "Connection: keep-alive\r\n\r\n")
3798 };
3799
3800 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593801 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023802 MockRead("HTTP/1.0 200 OK\r\n"),
3803 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3804 MockRead("Payload"),
3805 MockRead(false, OK)
3806 };
3807
[email protected]31a2bfe2010-02-09 08:03:393808 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3809 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593810 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023811
3812 TestCompletionCallback callback;
3813
[email protected]5a1d7ca2010-04-28 20:12:273814 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023815 EXPECT_EQ(ERR_IO_PENDING, rv);
3816
3817 rv = callback.WaitForResult();
3818 EXPECT_EQ(OK, rv);
3819
3820 const HttpResponseInfo* response = trans->GetResponseInfo();
3821 EXPECT_FALSE(response == NULL);
3822
3823 std::string response_text;
3824 rv = ReadTransaction(trans.get(), &response_text);
3825 EXPECT_EQ(OK, rv);
3826 EXPECT_EQ("Payload", response_text);
3827}
3828
3829TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093830 SessionDependencies session_deps(
3831 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023832
3833 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433834 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023835
3836 HttpRequestInfo request;
3837 request.method = "GET";
3838 request.url = GURL("https://www.google.com/");
3839 request.load_flags = 0;
3840
3841 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3842 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3843
3844 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353845 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3846 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023847 MockWrite("GET / HTTP/1.1\r\n"
3848 "Host: www.google.com\r\n"
3849 "Connection: keep-alive\r\n\r\n")
3850 };
3851
3852 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353853 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3854 arraysize(read_buffer)),
3855 MockRead("HTTP/1.0 200 OK\r\n"),
3856 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3857 MockRead("Payload"),
3858 MockRead(false, OK)
3859 };
3860
[email protected]31a2bfe2010-02-09 08:03:393861 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3862 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593863 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353864
[email protected]5ecc992a42009-11-11 01:41:593865 SSLSocketDataProvider ssl(true, OK);
3866 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353867
3868 TestCompletionCallback callback;
3869
[email protected]5a1d7ca2010-04-28 20:12:273870 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353871 EXPECT_EQ(ERR_IO_PENDING, rv);
3872
3873 rv = callback.WaitForResult();
3874 EXPECT_EQ(OK, rv);
3875
3876 const HttpResponseInfo* response = trans->GetResponseInfo();
3877 EXPECT_FALSE(response == NULL);
3878
3879 std::string response_text;
3880 rv = ReadTransaction(trans.get(), &response_text);
3881 EXPECT_EQ(OK, rv);
3882 EXPECT_EQ("Payload", response_text);
3883}
3884
3885TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093886 SessionDependencies session_deps(
3887 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353888
3889 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433890 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353891
3892 HttpRequestInfo request;
3893 request.method = "GET";
3894 request.url = GURL("http://www.google.com/");
3895 request.load_flags = 0;
3896
3897 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3898 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373899 const char kSOCKS5OkRequest[] = {
3900 0x05, // Version
3901 0x01, // Command (CONNECT)
3902 0x00, // Reserved.
3903 0x03, // Address type (DOMAINNAME).
3904 0x0E, // Length of domain (14)
3905 // Domain string:
3906 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3907 0x00, 0x50, // 16-bit port (80)
3908 };
[email protected]e0c27be2009-07-15 13:09:353909 const char kSOCKS5OkResponse[] =
3910 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3911
3912 MockWrite data_writes[] = {
3913 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3914 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3915 MockWrite("GET / HTTP/1.1\r\n"
3916 "Host: www.google.com\r\n"
3917 "Connection: keep-alive\r\n\r\n")
3918 };
3919
3920 MockRead data_reads[] = {
3921 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3922 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3923 MockRead("HTTP/1.0 200 OK\r\n"),
3924 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3925 MockRead("Payload"),
3926 MockRead(false, OK)
3927 };
3928
[email protected]31a2bfe2010-02-09 08:03:393929 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3930 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593931 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353932
3933 TestCompletionCallback callback;
3934
[email protected]5a1d7ca2010-04-28 20:12:273935 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353936 EXPECT_EQ(ERR_IO_PENDING, rv);
3937
3938 rv = callback.WaitForResult();
3939 EXPECT_EQ(OK, rv);
3940
3941 const HttpResponseInfo* response = trans->GetResponseInfo();
3942 EXPECT_FALSE(response == NULL);
3943
3944 std::string response_text;
3945 rv = ReadTransaction(trans.get(), &response_text);
3946 EXPECT_EQ(OK, rv);
3947 EXPECT_EQ("Payload", response_text);
3948}
3949
3950TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093951 SessionDependencies session_deps(
3952 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353953
3954 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433955 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353956
3957 HttpRequestInfo request;
3958 request.method = "GET";
3959 request.url = GURL("https://www.google.com/");
3960 request.load_flags = 0;
3961
3962 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3963 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373964 const unsigned char kSOCKS5OkRequest[] = {
3965 0x05, // Version
3966 0x01, // Command (CONNECT)
3967 0x00, // Reserved.
3968 0x03, // Address type (DOMAINNAME).
3969 0x0E, // Length of domain (14)
3970 // Domain string:
3971 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3972 0x01, 0xBB, // 16-bit port (443)
3973 };
3974
[email protected]e0c27be2009-07-15 13:09:353975 const char kSOCKS5OkResponse[] =
3976 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3977
3978 MockWrite data_writes[] = {
3979 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3980 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3981 arraysize(kSOCKS5OkRequest)),
3982 MockWrite("GET / HTTP/1.1\r\n"
3983 "Host: www.google.com\r\n"
3984 "Connection: keep-alive\r\n\r\n")
3985 };
3986
3987 MockRead data_reads[] = {
3988 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3989 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023990 MockRead("HTTP/1.0 200 OK\r\n"),
3991 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3992 MockRead("Payload"),
3993 MockRead(false, OK)
3994 };
3995
[email protected]31a2bfe2010-02-09 08:03:393996 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3997 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593998 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023999
[email protected]5ecc992a42009-11-11 01:41:594000 SSLSocketDataProvider ssl(true, OK);
4001 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:024002
4003 TestCompletionCallback callback;
4004
[email protected]5a1d7ca2010-04-28 20:12:274005 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024006 EXPECT_EQ(ERR_IO_PENDING, rv);
4007
4008 rv = callback.WaitForResult();
4009 EXPECT_EQ(OK, rv);
4010
4011 const HttpResponseInfo* response = trans->GetResponseInfo();
4012 EXPECT_FALSE(response == NULL);
4013
4014 std::string response_text;
4015 rv = ReadTransaction(trans.get(), &response_text);
4016 EXPECT_EQ(OK, rv);
4017 EXPECT_EQ("Payload", response_text);
4018}
4019
[email protected]04e5be32009-06-26 20:00:314020// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:064021
4022struct GroupNameTest {
4023 std::string proxy_server;
4024 std::string url;
4025 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:184026 bool ssl;
[email protected]2d731a32010-04-29 01:04:064027};
4028
4029scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
4030 const std::string& proxy_server) {
4031 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
4032 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4033
4034 HttpAlternateProtocols* alternate_protocols =
4035 session->mutable_alternate_protocols();
4036 alternate_protocols->SetAlternateProtocolFor(
4037 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:354038 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:064039
4040 return session;
4041}
4042
4043int GroupNameTransactionHelper(
4044 const std::string& url,
4045 const scoped_refptr<HttpNetworkSession>& session) {
4046 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4047
4048 HttpRequestInfo request;
4049 request.method = "GET";
4050 request.url = GURL(url);
4051 request.load_flags = 0;
4052
4053 TestCompletionCallback callback;
4054
4055 // We do not complete this request, the dtor will clean the transaction up.
4056 return trans->Start(&request, &callback, BoundNetLog());
4057}
4058
4059TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
4060 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:314061 {
[email protected]2d731a32010-04-29 01:04:064062 "", // unused
[email protected]04e5be32009-06-26 20:00:314063 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544064 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184065 false,
[email protected]2ff8b312010-04-26 22:20:544066 },
4067 {
[email protected]2d731a32010-04-29 01:04:064068 "", // unused
[email protected]2ff8b312010-04-26 22:20:544069 "http://[2001:1418:13:1::25]/direct",
4070 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:184071 false,
[email protected]04e5be32009-06-26 20:00:314072 },
[email protected]04e5be32009-06-26 20:00:314073
4074 // SSL Tests
4075 {
[email protected]2d731a32010-04-29 01:04:064076 "", // unused
[email protected]04e5be32009-06-26 20:00:314077 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024078 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184079 true,
[email protected]04e5be32009-06-26 20:00:314080 },
4081 {
[email protected]2d731a32010-04-29 01:04:064082 "", // unused
4083 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024084 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:184085 true,
[email protected]04e5be32009-06-26 20:00:314086 },
4087 {
[email protected]2d731a32010-04-29 01:04:064088 "", // unused
[email protected]2ff8b312010-04-26 22:20:544089 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024090 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184091 true,
[email protected]2ff8b312010-04-26 22:20:544092 },
[email protected]2d731a32010-04-29 01:04:064093 };
[email protected]2ff8b312010-04-26 22:20:544094
[email protected]2d731a32010-04-29 01:04:064095 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4096
4097 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4098 scoped_refptr<HttpNetworkSession> session(
4099 SetupSessionForGroupNameTests(tests[i].proxy_server));
4100
4101 HttpNetworkSessionPeer peer(session);
4102 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
4103 new CaptureGroupNameTCPSocketPool(session.get()));
4104 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]e60e47a2010-07-14 03:37:184105 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4106 new CaptureGroupNameSSLSocketPool(session.get()));
4107 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064108
4109 EXPECT_EQ(ERR_IO_PENDING,
4110 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184111 if (tests[i].ssl)
4112 EXPECT_EQ(tests[i].expected_group_name,
4113 ssl_conn_pool->last_group_name_received());
4114 else
4115 EXPECT_EQ(tests[i].expected_group_name,
4116 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064117 }
4118
4119 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4120}
4121
4122TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
4123 const GroupNameTest tests[] = {
4124 {
4125 "http_proxy",
4126 "http://www.google.com/http_proxy_normal",
4127 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184128 false,
[email protected]2d731a32010-04-29 01:04:064129 },
4130
4131 // SSL Tests
4132 {
4133 "http_proxy",
4134 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024135 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184136 true,
[email protected]2d731a32010-04-29 01:04:064137 },
4138
[email protected]9faeded92010-04-29 20:03:054139 {
4140 "http_proxy",
4141 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024142 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184143 true,
[email protected]9faeded92010-04-29 20:03:054144 },
[email protected]2d731a32010-04-29 01:04:064145 };
4146
4147 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4148
4149 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4150 scoped_refptr<HttpNetworkSession> session(
4151 SetupSessionForGroupNameTests(tests[i].proxy_server));
4152
4153 HttpNetworkSessionPeer peer(session);
4154
[email protected]e60e47a2010-07-14 03:37:184155 HostPortPair proxy_host("http_proxy", 80);
[email protected]e772db3f2010-07-12 18:11:134156 scoped_refptr<CaptureGroupNameHttpProxySocketPool> http_proxy_pool(
4157 new CaptureGroupNameHttpProxySocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184158 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
4159 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4160 new CaptureGroupNameSSLSocketPool(session.get()));
4161 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064162
4163 EXPECT_EQ(ERR_IO_PENDING,
4164 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184165 if (tests[i].ssl)
4166 EXPECT_EQ(tests[i].expected_group_name,
4167 ssl_conn_pool->last_group_name_received());
4168 else
4169 EXPECT_EQ(tests[i].expected_group_name,
4170 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064171 }
4172
4173 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4174}
4175
4176TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4177 const GroupNameTest tests[] = {
4178 {
4179 "socks4://socks_proxy:1080",
4180 "http://www.google.com/socks4_direct",
4181 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184182 false,
[email protected]2d731a32010-04-29 01:04:064183 },
4184 {
4185 "socks5://socks_proxy:1080",
4186 "http://www.google.com/socks5_direct",
4187 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184188 false,
[email protected]2d731a32010-04-29 01:04:064189 },
4190
4191 // SSL Tests
4192 {
4193 "socks4://socks_proxy:1080",
4194 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024195 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184196 true,
[email protected]2d731a32010-04-29 01:04:064197 },
4198 {
4199 "socks5://socks_proxy:1080",
4200 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024201 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184202 true,
[email protected]2d731a32010-04-29 01:04:064203 },
4204
[email protected]9faeded92010-04-29 20:03:054205 {
4206 "socks4://socks_proxy:1080",
4207 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024208 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184209 true,
[email protected]9faeded92010-04-29 20:03:054210 },
[email protected]04e5be32009-06-26 20:00:314211 };
4212
[email protected]2ff8b312010-04-26 22:20:544213 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4214
[email protected]04e5be32009-06-26 20:00:314215 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064216 scoped_refptr<HttpNetworkSession> session(
4217 SetupSessionForGroupNameTests(tests[i].proxy_server));
4218 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314219
[email protected]e60e47a2010-07-14 03:37:184220 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]a796bcec2010-03-22 17:17:264221 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064222 new CaptureGroupNameSOCKSSocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184223 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
4224 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4225 new CaptureGroupNameSSLSocketPool(session.get()));
4226 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:314227
[email protected]5695b8c2009-09-30 21:36:434228 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314229
[email protected]2d731a32010-04-29 01:04:064230 EXPECT_EQ(ERR_IO_PENDING,
4231 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184232 if (tests[i].ssl)
4233 EXPECT_EQ(tests[i].expected_group_name,
4234 ssl_conn_pool->last_group_name_received());
4235 else
4236 EXPECT_EQ(tests[i].expected_group_name,
4237 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314238 }
[email protected]2ff8b312010-04-26 22:20:544239
4240 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:314241}
4242
[email protected]9172a982009-06-06 00:30:254243TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544244 SessionDependencies session_deps(
4245 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324246
[email protected]69719062010-01-05 20:09:214247 // This simulates failure resolving all hostnames; that means we will fail
4248 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324249 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4250
[email protected]9172a982009-06-06 00:30:254251 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434252 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254253
4254 HttpRequestInfo request;
4255 request.method = "GET";
4256 request.url = GURL("http://www.google.com/");
4257
4258 TestCompletionCallback callback;
4259
[email protected]5a1d7ca2010-04-28 20:12:274260 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254261 EXPECT_EQ(ERR_IO_PENDING, rv);
4262
[email protected]9172a982009-06-06 00:30:254263 rv = callback.WaitForResult();
4264 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4265}
4266
[email protected]f3e6c1e2009-06-15 20:52:124267// Host resolution observer used by
4268// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4269// resovle requests are issued with a referrer of |expected_referrer|.
4270class ResolutionReferrerObserver : public HostResolver::Observer {
4271 public:
4272 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4273 : expected_referrer_(expected_referrer),
4274 called_start_with_referrer_(false),
4275 called_finish_with_referrer_(false) {
4276 }
4277
4278 virtual void OnStartResolution(int id,
4279 const HostResolver::RequestInfo& info) {
4280 if (info.referrer() == expected_referrer_)
4281 called_start_with_referrer_ = true;
4282 }
4283
4284 virtual void OnFinishResolutionWithStatus(
4285 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4286 if (info.referrer() == expected_referrer_)
4287 called_finish_with_referrer_ = true;
4288 }
4289
[email protected]eb255d32009-06-17 02:11:034290 virtual void OnCancelResolution(int id,
4291 const HostResolver::RequestInfo& info ) {
4292 FAIL() << "Should not be cancelling any requests!";
4293 }
4294
[email protected]f3e6c1e2009-06-15 20:52:124295 bool did_complete_with_expected_referrer() const {
4296 return called_start_with_referrer_ && called_finish_with_referrer_;
4297 }
4298
4299 private:
4300 GURL expected_referrer_;
4301 bool called_start_with_referrer_;
4302 bool called_finish_with_referrer_;
4303
4304 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4305};
4306
4307// Make sure that when HostResolver::Resolve() is invoked, it passes through
4308// the "referrer". This is depended on by the DNS prefetch observer.
4309TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4310 GURL referrer = GURL("http://expected-referrer/");
4311 EXPECT_TRUE(referrer.is_valid());
4312 ResolutionReferrerObserver resolution_observer(referrer);
4313
4314 SessionDependencies session_deps;
4315 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434316 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124317
4318 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144319 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124320
4321 // Connect up a mock socket which will fail when reading.
4322 MockRead data_reads[] = {
4323 MockRead(false, ERR_FAILED),
4324 };
[email protected]31a2bfe2010-02-09 08:03:394325 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594326 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124327
4328 // Issue a request, containing an HTTP referrer.
4329 HttpRequestInfo request;
4330 request.method = "GET";
4331 request.referrer = referrer;
4332 request.url = GURL("http://www.google.com/");
4333
4334 // Run the request until it fails reading from the socket.
4335 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274336 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124337 EXPECT_EQ(ERR_IO_PENDING, rv);
4338 rv = callback.WaitForResult();
4339 EXPECT_EQ(ERR_FAILED, rv);
4340
4341 // Check that the host resolution observer saw |referrer|.
4342 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4343}
4344
[email protected]685af592010-05-11 19:31:244345// Base test to make sure that when the load flags for a request specify to
4346// bypass the cache, the DNS cache is not used.
4347void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284348 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324349
[email protected]a2c2fb92009-07-18 07:31:044350 // Select a host resolver that does caching.
4351 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324352
[email protected]3b9cca42009-06-16 01:08:284353 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434354 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284355
4356 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4357 // a synchronous lookup.)
4358 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144359 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464360 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274361 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284362 EXPECT_EQ(OK, rv);
4363
4364 // Verify that it was added to host cache, by doing a subsequent async lookup
4365 // and confirming it completes synchronously.
4366 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464367 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284368 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274369 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324370 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284371
4372 // Inject a failure the next time that "www.google.com" is resolved. This way
4373 // we can tell if the next lookup hit the cache, or the "network".
4374 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324375 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284376
4377 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4378 // first read -- this won't be reached as the host resolution will fail first.
4379 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394380 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594381 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284382
4383 // Issue a request, asking to bypass the cache(s).
4384 HttpRequestInfo request;
4385 request.method = "GET";
[email protected]685af592010-05-11 19:31:244386 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284387 request.url = GURL("http://www.google.com/");
4388
4389 // Run the request.
4390 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274391 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284392 ASSERT_EQ(ERR_IO_PENDING, rv);
4393 rv = callback.WaitForResult();
4394
4395 // If we bypassed the cache, we would have gotten a failure while resolving
4396 // "www.google.com".
4397 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4398}
4399
[email protected]685af592010-05-11 19:31:244400// There are multiple load flags that should trigger the host cache bypass.
4401// Test each in isolation:
4402TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4403 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4404}
4405
4406TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4407 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4408}
4409
4410TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
4411 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
4412}
4413
[email protected]0877e3d2009-10-17 22:29:574414// Make sure we can handle an error when writing the request.
4415TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4416 SessionDependencies session_deps;
4417 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4418
4419 HttpRequestInfo request;
4420 request.method = "GET";
4421 request.url = GURL("http://www.foo.com/");
4422 request.load_flags = 0;
4423
4424 MockWrite write_failure[] = {
4425 MockWrite(true, ERR_CONNECTION_RESET),
4426 };
[email protected]31a2bfe2010-02-09 08:03:394427 StaticSocketDataProvider data(NULL, 0,
4428 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594429 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574430
4431 TestCompletionCallback callback;
4432
4433 scoped_ptr<HttpTransaction> trans(
4434 new HttpNetworkTransaction(CreateSession(&session_deps)));
4435
[email protected]5a1d7ca2010-04-28 20:12:274436 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574437 EXPECT_EQ(ERR_IO_PENDING, rv);
4438
4439 rv = callback.WaitForResult();
4440 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4441}
4442
4443// Check that a connection closed after the start of the headers finishes ok.
4444TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4445 SessionDependencies session_deps;
4446 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4447
4448 HttpRequestInfo request;
4449 request.method = "GET";
4450 request.url = GURL("http://www.foo.com/");
4451 request.load_flags = 0;
4452
4453 MockRead data_reads[] = {
4454 MockRead("HTTP/1."),
4455 MockRead(false, OK),
4456 };
4457
[email protected]31a2bfe2010-02-09 08:03:394458 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594459 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574460
4461 TestCompletionCallback callback;
4462
4463 scoped_ptr<HttpTransaction> trans(
4464 new HttpNetworkTransaction(CreateSession(&session_deps)));
4465
[email protected]5a1d7ca2010-04-28 20:12:274466 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574467 EXPECT_EQ(ERR_IO_PENDING, rv);
4468
4469 rv = callback.WaitForResult();
4470 EXPECT_EQ(OK, rv);
4471
4472 const HttpResponseInfo* response = trans->GetResponseInfo();
4473 EXPECT_TRUE(response != NULL);
4474
4475 EXPECT_TRUE(response->headers != NULL);
4476 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4477
4478 std::string response_data;
4479 rv = ReadTransaction(trans.get(), &response_data);
4480 EXPECT_EQ(OK, rv);
4481 EXPECT_EQ("", response_data);
4482}
4483
4484// Make sure that a dropped connection while draining the body for auth
4485// restart does the right thing.
4486TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4487 SessionDependencies session_deps;
4488 scoped_ptr<HttpTransaction> trans(
4489 new HttpNetworkTransaction(CreateSession(&session_deps)));
4490
4491 HttpRequestInfo request;
4492 request.method = "GET";
4493 request.url = GURL("http://www.google.com/");
4494 request.load_flags = 0;
4495
4496 MockWrite data_writes1[] = {
4497 MockWrite("GET / HTTP/1.1\r\n"
4498 "Host: www.google.com\r\n"
4499 "Connection: keep-alive\r\n\r\n"),
4500 };
4501
4502 MockRead data_reads1[] = {
4503 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4504 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4505 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4506 MockRead("Content-Length: 14\r\n\r\n"),
4507 MockRead("Unauth"),
4508 MockRead(true, ERR_CONNECTION_RESET),
4509 };
4510
[email protected]31a2bfe2010-02-09 08:03:394511 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4512 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594513 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574514
4515 // After calling trans->RestartWithAuth(), this is the request we should
4516 // be issuing -- the final header line contains the credentials.
4517 MockWrite data_writes2[] = {
4518 MockWrite("GET / HTTP/1.1\r\n"
4519 "Host: www.google.com\r\n"
4520 "Connection: keep-alive\r\n"
4521 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4522 };
4523
4524 // Lastly, the server responds with the actual content.
4525 MockRead data_reads2[] = {
4526 MockRead("HTTP/1.1 200 OK\r\n"),
4527 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4528 MockRead("Content-Length: 100\r\n\r\n"),
4529 MockRead(false, OK),
4530 };
4531
[email protected]31a2bfe2010-02-09 08:03:394532 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4533 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594534 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574535
4536 TestCompletionCallback callback1;
4537
[email protected]5a1d7ca2010-04-28 20:12:274538 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574539 EXPECT_EQ(ERR_IO_PENDING, rv);
4540
4541 rv = callback1.WaitForResult();
4542 EXPECT_EQ(OK, rv);
4543
4544 const HttpResponseInfo* response = trans->GetResponseInfo();
4545 EXPECT_FALSE(response == NULL);
4546
4547 // The password prompt info should have been set in response->auth_challenge.
4548 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4549
4550 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4551 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4552 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4553
4554 TestCompletionCallback callback2;
4555
[email protected]13c8a092010-07-29 06:15:444556 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:574557 EXPECT_EQ(ERR_IO_PENDING, rv);
4558
4559 rv = callback2.WaitForResult();
4560 EXPECT_EQ(OK, rv);
4561
4562 response = trans->GetResponseInfo();
4563 EXPECT_FALSE(response == NULL);
4564 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4565 EXPECT_EQ(100, response->headers->GetContentLength());
4566}
4567
4568// Test HTTPS connections going through a proxy that sends extra data.
4569TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4570 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4571
4572 HttpRequestInfo request;
4573 request.method = "GET";
4574 request.url = GURL("https://www.google.com/");
4575 request.load_flags = 0;
4576
4577 MockRead proxy_reads[] = {
4578 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4579 MockRead(false, OK)
4580 };
4581
[email protected]31a2bfe2010-02-09 08:03:394582 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594583 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574584
[email protected]5ecc992a42009-11-11 01:41:594585 session_deps.socket_factory.AddSocketDataProvider(&data);
4586 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574587
4588 TestCompletionCallback callback;
4589
4590 session_deps.socket_factory.ResetNextMockIndexes();
4591
4592 scoped_ptr<HttpTransaction> trans(
4593 new HttpNetworkTransaction(CreateSession(&session_deps)));
4594
[email protected]5a1d7ca2010-04-28 20:12:274595 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574596 EXPECT_EQ(ERR_IO_PENDING, rv);
4597
4598 rv = callback.WaitForResult();
4599 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4600}
4601
[email protected]e22e1362009-11-23 21:31:124602TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464603 SessionDependencies session_deps;
4604 scoped_ptr<HttpTransaction> trans(
4605 new HttpNetworkTransaction(CreateSession(&session_deps)));
4606
4607 HttpRequestInfo request;
4608 request.method = "GET";
4609 request.url = GURL("http://www.google.com/");
4610 request.load_flags = 0;
4611
[email protected]e22e1362009-11-23 21:31:124612 MockRead data_reads[] = {
4613 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4614 MockRead(false, OK),
4615 };
[email protected]9492e4a2010-02-24 00:58:464616
4617 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4618 session_deps.socket_factory.AddSocketDataProvider(&data);
4619
4620 TestCompletionCallback callback;
4621
[email protected]5a1d7ca2010-04-28 20:12:274622 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464623 EXPECT_EQ(ERR_IO_PENDING, rv);
4624
4625 EXPECT_EQ(OK, callback.WaitForResult());
4626
4627 const HttpResponseInfo* response = trans->GetResponseInfo();
4628 EXPECT_TRUE(response != NULL);
4629
4630 EXPECT_TRUE(response->headers != NULL);
4631 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4632
4633 std::string response_data;
4634 rv = ReadTransaction(trans.get(), &response_data);
4635 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124636}
4637
[email protected]95d88ffe2010-02-04 21:25:334638TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4639 SessionDependencies session_deps;
4640 scoped_ptr<HttpTransaction> trans(
4641 new HttpNetworkTransaction(CreateSession(&session_deps)));
4642
4643 HttpRequestInfo request;
4644 request.method = "POST";
4645 request.url = GURL("http://www.google.com/upload");
4646 request.upload_data = new UploadData;
4647 request.load_flags = 0;
4648
4649 FilePath temp_file_path;
4650 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4651 const uint64 kFakeSize = 100000; // file is actually blank
4652
4653 std::vector<UploadData::Element> elements;
4654 UploadData::Element element;
4655 element.SetToFilePath(temp_file_path);
4656 element.SetContentLength(kFakeSize);
4657 elements.push_back(element);
4658 request.upload_data->set_elements(elements);
4659 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4660
4661 MockRead data_reads[] = {
4662 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4663 MockRead("hello world"),
4664 MockRead(false, OK),
4665 };
[email protected]31a2bfe2010-02-09 08:03:394666 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334667 session_deps.socket_factory.AddSocketDataProvider(&data);
4668
4669 TestCompletionCallback callback;
4670
[email protected]5a1d7ca2010-04-28 20:12:274671 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334672 EXPECT_EQ(ERR_IO_PENDING, rv);
4673
4674 rv = callback.WaitForResult();
4675 EXPECT_EQ(OK, rv);
4676
4677 const HttpResponseInfo* response = trans->GetResponseInfo();
4678 EXPECT_TRUE(response != NULL);
4679
4680 EXPECT_TRUE(response->headers != NULL);
4681 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4682
4683 std::string response_data;
4684 rv = ReadTransaction(trans.get(), &response_data);
4685 EXPECT_EQ(OK, rv);
4686 EXPECT_EQ("hello world", response_data);
4687
4688 file_util::Delete(temp_file_path, false);
4689}
4690
[email protected]6624b4622010-03-29 19:58:364691TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4692 // If we try to upload an unreadable file, the network stack should report
4693 // the file size as zero and upload zero bytes for that file.
4694 SessionDependencies session_deps;
4695 scoped_ptr<HttpTransaction> trans(
4696 new HttpNetworkTransaction(CreateSession(&session_deps)));
4697
4698 FilePath temp_file;
4699 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4700 std::string temp_file_content("Unreadable file.");
4701 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4702 temp_file_content.length()));
4703 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4704
4705 HttpRequestInfo request;
4706 request.method = "POST";
4707 request.url = GURL("http://www.google.com/upload");
4708 request.upload_data = new UploadData;
4709 request.load_flags = 0;
4710
4711 std::vector<UploadData::Element> elements;
4712 UploadData::Element element;
4713 element.SetToFilePath(temp_file);
4714 elements.push_back(element);
4715 request.upload_data->set_elements(elements);
4716
4717 MockRead data_reads[] = {
4718 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4719 MockRead(false, OK),
4720 };
4721 MockWrite data_writes[] = {
4722 MockWrite("POST /upload HTTP/1.1\r\n"
4723 "Host: www.google.com\r\n"
4724 "Connection: keep-alive\r\n"
4725 "Content-Length: 0\r\n\r\n"),
4726 MockWrite(false, OK),
4727 };
4728 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4729 arraysize(data_writes));
4730 session_deps.socket_factory.AddSocketDataProvider(&data);
4731
4732 TestCompletionCallback callback;
4733
[email protected]5a1d7ca2010-04-28 20:12:274734 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364735 EXPECT_EQ(ERR_IO_PENDING, rv);
4736
4737 rv = callback.WaitForResult();
4738 EXPECT_EQ(OK, rv);
4739
4740 const HttpResponseInfo* response = trans->GetResponseInfo();
4741 EXPECT_TRUE(response != NULL);
4742 EXPECT_TRUE(response->headers != NULL);
4743 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4744
4745 file_util::Delete(temp_file, false);
4746}
4747
4748TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4749 SessionDependencies session_deps;
4750 scoped_ptr<HttpTransaction> trans(
4751 new HttpNetworkTransaction(CreateSession(&session_deps)));
4752
4753 FilePath temp_file;
4754 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4755 std::string temp_file_contents("Unreadable file.");
4756 std::string unreadable_contents(temp_file_contents.length(), '\0');
4757 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4758 temp_file_contents.length()));
4759
4760 HttpRequestInfo request;
4761 request.method = "POST";
4762 request.url = GURL("http://www.google.com/upload");
4763 request.upload_data = new UploadData;
4764 request.load_flags = 0;
4765
4766 std::vector<UploadData::Element> elements;
4767 UploadData::Element element;
4768 element.SetToFilePath(temp_file);
4769 elements.push_back(element);
4770 request.upload_data->set_elements(elements);
4771
4772 MockRead data_reads[] = {
4773 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4774 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4775 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4776
4777 MockRead("HTTP/1.1 200 OK\r\n"),
4778 MockRead("Content-Length: 0\r\n\r\n"),
4779 MockRead(false, OK),
4780 };
4781 MockWrite data_writes[] = {
4782 MockWrite("POST /upload HTTP/1.1\r\n"
4783 "Host: www.google.com\r\n"
4784 "Connection: keep-alive\r\n"
4785 "Content-Length: 16\r\n\r\n"),
4786 MockWrite(false, temp_file_contents.c_str()),
4787
4788 MockWrite("POST /upload HTTP/1.1\r\n"
4789 "Host: www.google.com\r\n"
4790 "Connection: keep-alive\r\n"
4791 "Content-Length: 16\r\n"
4792 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4793 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4794 MockWrite(false, OK),
4795 };
4796 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4797 arraysize(data_writes));
4798 session_deps.socket_factory.AddSocketDataProvider(&data);
4799
4800 TestCompletionCallback callback1;
4801
[email protected]5a1d7ca2010-04-28 20:12:274802 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364803 EXPECT_EQ(ERR_IO_PENDING, rv);
4804
4805 rv = callback1.WaitForResult();
4806 EXPECT_EQ(OK, rv);
4807
4808 const HttpResponseInfo* response = trans->GetResponseInfo();
4809 EXPECT_TRUE(response != NULL);
4810 EXPECT_TRUE(response->headers != NULL);
4811 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4812
4813 // The password prompt info should have been set in response->auth_challenge.
4814 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4815 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4816 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4817 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4818
4819 // Now make the file unreadable and try again.
4820 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4821
4822 TestCompletionCallback callback2;
4823
[email protected]13c8a092010-07-29 06:15:444824 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:364825 EXPECT_EQ(ERR_IO_PENDING, rv);
4826
4827 rv = callback2.WaitForResult();
4828 EXPECT_EQ(OK, rv);
4829
4830 response = trans->GetResponseInfo();
4831 EXPECT_TRUE(response != NULL);
4832 EXPECT_TRUE(response->headers != NULL);
4833 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4834 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4835
4836 file_util::Delete(temp_file, false);
4837}
4838
[email protected]aeefc9e82010-02-19 16:18:274839// Tests that changes to Auth realms are treated like auth rejections.
4840TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4841 SessionDependencies session_deps;
4842 scoped_ptr<HttpTransaction> trans(
4843 new HttpNetworkTransaction(CreateSession(&session_deps)));
4844
4845 HttpRequestInfo request;
4846 request.method = "GET";
4847 request.url = GURL("http://www.google.com/");
4848 request.load_flags = 0;
4849
4850 // First transaction will request a resource and receive a Basic challenge
4851 // with realm="first_realm".
4852 MockWrite data_writes1[] = {
4853 MockWrite("GET / HTTP/1.1\r\n"
4854 "Host: www.google.com\r\n"
4855 "Connection: keep-alive\r\n"
4856 "\r\n"),
4857 };
4858 MockRead data_reads1[] = {
4859 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4860 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4861 "\r\n"),
4862 };
4863
4864 // After calling trans->RestartWithAuth(), provide an Authentication header
4865 // for first_realm. The server will reject and provide a challenge with
4866 // second_realm.
4867 MockWrite data_writes2[] = {
4868 MockWrite("GET / HTTP/1.1\r\n"
4869 "Host: www.google.com\r\n"
4870 "Connection: keep-alive\r\n"
4871 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4872 "\r\n"),
4873 };
4874 MockRead data_reads2[] = {
4875 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4876 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4877 "\r\n"),
4878 };
4879
4880 // This again fails, and goes back to first_realm. Make sure that the
4881 // entry is removed from cache.
4882 MockWrite data_writes3[] = {
4883 MockWrite("GET / HTTP/1.1\r\n"
4884 "Host: www.google.com\r\n"
4885 "Connection: keep-alive\r\n"
4886 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4887 "\r\n"),
4888 };
4889 MockRead data_reads3[] = {
4890 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4891 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4892 "\r\n"),
4893 };
4894
4895 // Try one last time (with the correct password) and get the resource.
4896 MockWrite data_writes4[] = {
4897 MockWrite("GET / HTTP/1.1\r\n"
4898 "Host: www.google.com\r\n"
4899 "Connection: keep-alive\r\n"
4900 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4901 "\r\n"),
4902 };
4903 MockRead data_reads4[] = {
4904 MockRead("HTTP/1.1 200 OK\r\n"
4905 "Content-Type: text/html; charset=iso-8859-1\r\n"
4906 "Content-Length: 100\r\n"
4907 "\r\n"),
4908 };
4909
4910 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4911 data_writes1, arraysize(data_writes1));
4912 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4913 data_writes2, arraysize(data_writes2));
4914 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4915 data_writes3, arraysize(data_writes3));
4916 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4917 data_writes4, arraysize(data_writes4));
4918 session_deps.socket_factory.AddSocketDataProvider(&data1);
4919 session_deps.socket_factory.AddSocketDataProvider(&data2);
4920 session_deps.socket_factory.AddSocketDataProvider(&data3);
4921 session_deps.socket_factory.AddSocketDataProvider(&data4);
4922
4923 TestCompletionCallback callback1;
4924
4925 // Issue the first request with Authorize headers. There should be a
4926 // password prompt for first_realm waiting to be filled in after the
4927 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:274928 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:274929 EXPECT_EQ(ERR_IO_PENDING, rv);
4930 rv = callback1.WaitForResult();
4931 EXPECT_EQ(OK, rv);
4932 const HttpResponseInfo* response = trans->GetResponseInfo();
4933 ASSERT_FALSE(response == NULL);
4934 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4935 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4936 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4937 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4938
4939 // Issue the second request with an incorrect password. There should be a
4940 // password prompt for second_realm waiting to be filled in after the
4941 // transaction completes.
4942 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444943 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:274944 EXPECT_EQ(ERR_IO_PENDING, rv);
4945 rv = callback2.WaitForResult();
4946 EXPECT_EQ(OK, rv);
4947 response = trans->GetResponseInfo();
4948 ASSERT_FALSE(response == NULL);
4949 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4950 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4951 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4952 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4953
4954 // Issue the third request with another incorrect password. There should be
4955 // a password prompt for first_realm waiting to be filled in. If the password
4956 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4957 // first_realm was not correctly removed.
4958 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:444959 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:274960 EXPECT_EQ(ERR_IO_PENDING, rv);
4961 rv = callback3.WaitForResult();
4962 EXPECT_EQ(OK, rv);
4963 response = trans->GetResponseInfo();
4964 ASSERT_FALSE(response == NULL);
4965 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4966 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4967 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4968 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4969
4970 // Issue the fourth request with the correct password and username.
4971 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:444972 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:274973 EXPECT_EQ(ERR_IO_PENDING, rv);
4974 rv = callback4.WaitForResult();
4975 EXPECT_EQ(OK, rv);
4976 response = trans->GetResponseInfo();
4977 ASSERT_FALSE(response == NULL);
4978 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4979}
4980
[email protected]564b4912010-03-09 16:30:424981TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424982 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:064983 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:424984
[email protected]564b4912010-03-09 16:30:424985 SessionDependencies session_deps;
4986
4987 MockRead data_reads[] = {
4988 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:354989 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:424990 MockRead("hello world"),
4991 MockRead(false, OK),
4992 };
4993
4994 HttpRequestInfo request;
4995 request.method = "GET";
4996 request.url = GURL("http://www.google.com/");
4997 request.load_flags = 0;
4998
4999 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5000
5001 session_deps.socket_factory.AddSocketDataProvider(&data);
5002
5003 TestCompletionCallback callback;
5004
5005 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5006 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5007
[email protected]5a1d7ca2010-04-28 20:12:275008 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425009 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:535010
[email protected]2fbaecf22010-07-22 22:20:355011 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425012 const HttpAlternateProtocols& alternate_protocols =
5013 session->alternate_protocols();
5014 EXPECT_FALSE(
5015 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5016
5017 EXPECT_EQ(OK, callback.WaitForResult());
5018
5019 const HttpResponseInfo* response = trans->GetResponseInfo();
5020 ASSERT_TRUE(response != NULL);
5021 ASSERT_TRUE(response->headers != NULL);
5022 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535023 EXPECT_FALSE(response->was_fetched_via_spdy);
5024 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575025 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:425026
5027 std::string response_data;
5028 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5029 EXPECT_EQ("hello world", response_data);
5030
5031 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5032 const HttpAlternateProtocols::PortProtocolPair alternate =
5033 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
5034 HttpAlternateProtocols::PortProtocolPair expected_alternate;
5035 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:355036 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:425037 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:425038
[email protected]31e2c69e2010-04-15 18:06:065039 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:425040 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:425041}
5042
5043TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:065044 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:425045 SessionDependencies session_deps;
5046
5047 HttpRequestInfo request;
5048 request.method = "GET";
5049 request.url = GURL("http://www.google.com/");
5050 request.load_flags = 0;
5051
5052 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
5053 StaticSocketDataProvider first_data;
5054 first_data.set_connect_data(mock_connect);
5055 session_deps.socket_factory.AddSocketDataProvider(&first_data);
5056
5057 MockRead data_reads[] = {
5058 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5059 MockRead("hello world"),
5060 MockRead(true, OK),
5061 };
5062 StaticSocketDataProvider second_data(
5063 data_reads, arraysize(data_reads), NULL, 0);
5064 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5065
5066 // TODO(willchan): Delete this extra data provider. It's necessary due to a
5067 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
5068 // http://crbug.com/37454.
5069 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5070
5071 TestCompletionCallback callback;
5072
5073 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5074
[email protected]2fbaecf22010-07-22 22:20:355075 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425076 HttpAlternateProtocols* alternate_protocols =
5077 session->mutable_alternate_protocols();
5078 alternate_protocols->SetAlternateProtocolFor(
5079 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:355080 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425081
5082 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5083
[email protected]5a1d7ca2010-04-28 20:12:275084 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425085 EXPECT_EQ(ERR_IO_PENDING, rv);
5086 EXPECT_EQ(OK, callback.WaitForResult());
5087
5088 const HttpResponseInfo* response = trans->GetResponseInfo();
5089 ASSERT_TRUE(response != NULL);
5090 ASSERT_TRUE(response->headers != NULL);
5091 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5092
5093 std::string response_data;
5094 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5095 EXPECT_EQ("hello world", response_data);
5096
5097 ASSERT_TRUE(
5098 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
5099 const HttpAlternateProtocols::PortProtocolPair alternate =
5100 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
5101 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:065102 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425103}
5104
5105// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
5106// says that it does SPDY, but it just does the TLS handshake, but the NPN
5107// response does not indicate SPDY, so we just do standard HTTPS over the port.
5108// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
5109// on the original port.
[email protected]a2cb8122010-03-10 17:22:425110// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
5111// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:535112//
[email protected]a2cb8122010-03-10 17:22:425113// HttpRequestInfo request;
5114// request.method = "GET";
5115// request.url = GURL("http://www.google.com/");
5116// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:535117//
[email protected]a2cb8122010-03-10 17:22:425118// MockRead data_reads[] = {
5119// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5120// MockRead("hello world"),
5121// MockRead(true, OK),
5122// };
5123// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5124// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:535125//
[email protected]a2cb8122010-03-10 17:22:425126// SSLSocketDataProvider ssl(true, OK);
5127// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:535128//
[email protected]a2cb8122010-03-10 17:22:425129// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:535130//
[email protected]a2cb8122010-03-10 17:22:425131// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:535132//
[email protected]a2cb8122010-03-10 17:22:425133// HostPortPair http_host_port_pair;
5134// http_host_port_pair.host = "www.google.com";
5135// http_host_port_pair.port = 80;
5136// HttpAlternateProtocols* alternate_protocols =
5137// session->mutable_alternate_protocols();
5138// alternate_protocols->SetAlternateProtocolFor(
5139// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065140// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:535141//
[email protected]a2cb8122010-03-10 17:22:425142// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:535143//
[email protected]5a1d7ca2010-04-28 20:12:275144// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:425145// EXPECT_EQ(ERR_IO_PENDING, rv);
5146// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:535147//
[email protected]a2cb8122010-03-10 17:22:425148// const HttpResponseInfo* response = trans->GetResponseInfo();
5149// ASSERT_TRUE(response != NULL);
5150// ASSERT_TRUE(response->headers != NULL);
5151// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535152//
[email protected]a2cb8122010-03-10 17:22:425153// std::string response_data;
5154// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5155// EXPECT_EQ("hello world", response_data);
5156// }
5157
5158TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:065159 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355160 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:425161 SessionDependencies session_deps;
5162
5163 HttpRequestInfo request;
5164 request.method = "GET";
5165 request.url = GURL("http://www.google.com/");
5166 request.load_flags = 0;
5167
[email protected]a2cb8122010-03-10 17:22:425168 StaticSocketDataProvider first_tcp_connect;
5169 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5170
5171 SSLSocketDataProvider ssl(true, OK);
5172 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5173
[email protected]564b4912010-03-09 16:30:425174 MockRead data_reads[] = {
5175 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5176 MockRead("hello world"),
5177 MockRead(true, OK),
5178 };
[email protected]a2cb8122010-03-10 17:22:425179 StaticSocketDataProvider fallback_data(
5180 data_reads, arraysize(data_reads), NULL, 0);
5181 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425182
5183 TestCompletionCallback callback;
5184
5185 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5186
[email protected]2fbaecf22010-07-22 22:20:355187 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425188 HttpAlternateProtocols* alternate_protocols =
5189 session->mutable_alternate_protocols();
5190 alternate_protocols->SetAlternateProtocolFor(
5191 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:355192 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425193
5194 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5195
[email protected]5a1d7ca2010-04-28 20:12:275196 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425197 EXPECT_EQ(ERR_IO_PENDING, rv);
5198 EXPECT_EQ(OK, callback.WaitForResult());
5199
5200 const HttpResponseInfo* response = trans->GetResponseInfo();
5201 ASSERT_TRUE(response != NULL);
5202 ASSERT_TRUE(response->headers != NULL);
5203 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5204
5205 std::string response_data;
5206 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5207 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:545208 HttpNetworkTransaction::SetNextProtos("");
5209 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5210}
5211
5212TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
5213 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355214 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545215 SessionDependencies session_deps;
5216
5217 HttpRequestInfo request;
5218 request.method = "GET";
5219 request.url = GURL("http://www.google.com/");
5220 request.load_flags = 0;
5221
5222 MockRead data_reads[] = {
5223 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355224 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545225 MockRead("hello world"),
5226 MockRead(true, OK),
5227 };
5228
5229 StaticSocketDataProvider first_transaction(
5230 data_reads, arraysize(data_reads), NULL, 0);
5231 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5232
5233 SSLSocketDataProvider ssl(true, OK);
5234 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355235 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535236 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545237 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5238
[email protected]2bd93022010-07-17 00:58:445239 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135240 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545241
[email protected]2bd93022010-07-17 00:58:445242 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5243 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545244 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135245 CreateMockRead(*resp),
5246 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545247 MockRead(true, 0, 0),
5248 };
5249
5250 scoped_refptr<DelayedSocketData> spdy_data(
5251 new DelayedSocketData(
5252 1, // wait for one write to finish before reading.
5253 spdy_reads, arraysize(spdy_reads),
5254 spdy_writes, arraysize(spdy_writes)));
5255 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5256
5257 TestCompletionCallback callback;
5258
5259 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5260 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5261
[email protected]5a1d7ca2010-04-28 20:12:275262 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545263 EXPECT_EQ(ERR_IO_PENDING, rv);
5264 EXPECT_EQ(OK, callback.WaitForResult());
5265
5266 const HttpResponseInfo* response = trans->GetResponseInfo();
5267 ASSERT_TRUE(response != NULL);
5268 ASSERT_TRUE(response->headers != NULL);
5269 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5270
5271 std::string response_data;
5272 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5273 EXPECT_EQ("hello world", response_data);
5274
5275 trans.reset(new HttpNetworkTransaction(session));
5276
[email protected]5a1d7ca2010-04-28 20:12:275277 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545278 EXPECT_EQ(ERR_IO_PENDING, rv);
5279 EXPECT_EQ(OK, callback.WaitForResult());
5280
5281 response = trans->GetResponseInfo();
5282 ASSERT_TRUE(response != NULL);
5283 ASSERT_TRUE(response->headers != NULL);
5284 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535285 EXPECT_TRUE(response->was_fetched_via_spdy);
5286 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575287 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545288
5289 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5290 EXPECT_EQ("hello!", response_data);
5291
5292 HttpNetworkTransaction::SetNextProtos("");
5293 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5294}
5295
[email protected]631f1322010-04-30 17:59:115296class CapturingProxyResolver : public ProxyResolver {
5297 public:
5298 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5299 virtual ~CapturingProxyResolver() {}
5300
5301 virtual int GetProxyForURL(const GURL& url,
5302 ProxyInfo* results,
5303 CompletionCallback* callback,
5304 RequestHandle* request,
5305 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:405306 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
5307 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:425308 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115309 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425310 return OK;
[email protected]631f1322010-04-30 17:59:115311 }
5312
5313 virtual void CancelRequest(RequestHandle request) {
5314 NOTREACHED();
5315 }
5316
[email protected]24476402010-07-20 20:55:175317 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:115318 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425319 return OK;
[email protected]631f1322010-04-30 17:59:115320 }
5321
[email protected]24476402010-07-20 20:55:175322 const std::vector<GURL>& resolved() const { return resolved_; }
5323
5324 private:
[email protected]631f1322010-04-30 17:59:115325 std::vector<GURL> resolved_;
5326
5327 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5328};
5329
[email protected]631f1322010-04-30 17:59:115330TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
5331 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355332 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:115333
5334 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425335 proxy_config.set_auto_detect(true);
5336 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115337
[email protected]631f1322010-04-30 17:59:115338 CapturingProxyResolver* capturing_proxy_resolver =
5339 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:385340 SessionDependencies session_deps(new ProxyService(
5341 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
5342 NULL));
[email protected]631f1322010-04-30 17:59:115343
5344 HttpRequestInfo request;
5345 request.method = "GET";
5346 request.url = GURL("http://www.google.com/");
5347 request.load_flags = 0;
5348
5349 MockRead data_reads[] = {
5350 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355351 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:115352 MockRead("hello world"),
5353 MockRead(true, OK),
5354 };
5355
5356 StaticSocketDataProvider first_transaction(
5357 data_reads, arraysize(data_reads), NULL, 0);
5358 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5359
5360 SSLSocketDataProvider ssl(true, OK);
5361 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355362 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535363 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:115364 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5365
[email protected]2bd93022010-07-17 00:58:445366 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:115367 MockWrite spdy_writes[] = {
5368 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5369 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425370 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:135371 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:115372 };
5373
[email protected]d911f1b2010-05-05 22:39:425374 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5375
[email protected]2bd93022010-07-17 00:58:445376 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5377 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:115378 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425379 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:135380 CreateMockRead(*resp.get(), 4), // 2, 4
5381 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:425382 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115383 };
5384
[email protected]d911f1b2010-05-05 22:39:425385 scoped_refptr<OrderedSocketData> spdy_data(
5386 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115387 spdy_reads, arraysize(spdy_reads),
5388 spdy_writes, arraysize(spdy_writes)));
5389 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5390
5391 TestCompletionCallback callback;
5392
5393 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5394 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5395
5396 int rv = trans->Start(&request, &callback, BoundNetLog());
5397 EXPECT_EQ(ERR_IO_PENDING, rv);
5398 EXPECT_EQ(OK, callback.WaitForResult());
5399
5400 const HttpResponseInfo* response = trans->GetResponseInfo();
5401 ASSERT_TRUE(response != NULL);
5402 ASSERT_TRUE(response->headers != NULL);
5403 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535404 EXPECT_FALSE(response->was_fetched_via_spdy);
5405 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115406
5407 std::string response_data;
5408 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5409 EXPECT_EQ("hello world", response_data);
5410
5411 trans.reset(new HttpNetworkTransaction(session));
5412
5413 rv = trans->Start(&request, &callback, BoundNetLog());
5414 EXPECT_EQ(ERR_IO_PENDING, rv);
5415 EXPECT_EQ(OK, callback.WaitForResult());
5416
5417 response = trans->GetResponseInfo();
5418 ASSERT_TRUE(response != NULL);
5419 ASSERT_TRUE(response->headers != NULL);
5420 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535421 EXPECT_TRUE(response->was_fetched_via_spdy);
5422 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115423
5424 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5425 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425426 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5427 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115428 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425429 EXPECT_EQ("https://www.google.com/",
5430 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115431
5432 HttpNetworkTransaction::SetNextProtos("");
5433 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5434}
[email protected]631f1322010-04-30 17:59:115435
[email protected]2ff8b312010-04-26 22:20:545436TEST_F(HttpNetworkTransactionTest,
5437 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5438 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355439 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545440 SessionDependencies session_deps;
5441
5442 HttpRequestInfo request;
5443 request.method = "GET";
5444 request.url = GURL("http://www.google.com/");
5445 request.load_flags = 0;
5446
5447 MockRead data_reads[] = {
5448 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355449 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545450 MockRead("hello world"),
5451 MockRead(true, OK),
5452 };
5453
5454 StaticSocketDataProvider first_transaction(
5455 data_reads, arraysize(data_reads), NULL, 0);
5456 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5457
5458 SSLSocketDataProvider ssl(true, OK);
5459 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355460 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535461 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545462 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:535463 // Make sure we use ssl for spdy here.
5464 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:545465
[email protected]2bd93022010-07-17 00:58:445466 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135467 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545468
[email protected]2bd93022010-07-17 00:58:445469 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5470 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545471 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135472 CreateMockRead(*resp),
5473 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545474 MockRead(true, 0, 0),
5475 };
5476
5477 scoped_refptr<DelayedSocketData> spdy_data(
5478 new DelayedSocketData(
5479 1, // wait for one write to finish before reading.
5480 spdy_reads, arraysize(spdy_reads),
5481 spdy_writes, arraysize(spdy_writes)));
5482 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5483
5484 TestCompletionCallback callback;
5485
5486 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5487
5488 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5489
[email protected]5a1d7ca2010-04-28 20:12:275490 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545491 EXPECT_EQ(ERR_IO_PENDING, rv);
5492 EXPECT_EQ(OK, callback.WaitForResult());
5493
5494 const HttpResponseInfo* response = trans->GetResponseInfo();
5495 ASSERT_TRUE(response != NULL);
5496 ASSERT_TRUE(response->headers != NULL);
5497 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5498
5499 std::string response_data;
5500 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5501 EXPECT_EQ("hello world", response_data);
5502
5503 // Set up an initial SpdySession in the pool to reuse.
[email protected]b261d0e2010-08-02 19:13:245504 HostPortProxyPair pair(HostPortPair("www.google.com", 443), "DIRECT");
[email protected]2ff8b312010-04-26 22:20:545505 scoped_refptr<SpdySession> spdy_session =
[email protected]b261d0e2010-08-02 19:13:245506 session->spdy_session_pool()->Get(pair, session, BoundNetLog());
[email protected]df4b4ef2010-07-12 18:25:215507 scoped_refptr<TCPSocketParams> tcp_params =
5508 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:365509 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:545510 trans.reset(new HttpNetworkTransaction(session));
5511
[email protected]5a1d7ca2010-04-28 20:12:275512 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545513 EXPECT_EQ(ERR_IO_PENDING, rv);
5514 EXPECT_EQ(OK, callback.WaitForResult());
5515
5516 response = trans->GetResponseInfo();
5517 ASSERT_TRUE(response != NULL);
5518 ASSERT_TRUE(response->headers != NULL);
5519 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535520 EXPECT_TRUE(response->was_fetched_via_spdy);
5521 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575522 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545523
5524 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5525 EXPECT_EQ("hello!", response_data);
5526
5527 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065528 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425529}
5530
[email protected]044de0642010-06-17 10:42:155531// GenerateAuthToken is a mighty big test.
5532// It tests all permutation of GenerateAuthToken behavior:
5533// - Synchronous and Asynchronous completion.
5534// - OK or error on completion.
5535// - Direct connection, non-authenticating proxy, and authenticating proxy.
5536// - HTTP or HTTPS backend (to include proxy tunneling).
5537// - Non-authenticating and authenticating backend.
5538//
5539// In all, there are 44 reasonable permuations (for example, if there are
5540// problems generating an auth token for an authenticating proxy, we don't
5541// need to test all permutations of the backend server).
5542//
5543// The test proceeds by going over each of the configuration cases, and
5544// potentially running up to three rounds in each of the tests. The TestConfig
5545// specifies both the configuration for the test as well as the expectations
5546// for the results.
5547TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
5548 const char* kServer = "http://www.example.com";
5549 const char* kSecureServer = "https://www.example.com";
5550 const char* kProxy = "myproxy:70";
5551 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
5552
5553 enum AuthTiming {
5554 AUTH_NONE,
5555 AUTH_SYNC,
5556 AUTH_ASYNC,
5557 };
5558
5559 const MockWrite kGet(
5560 "GET / HTTP/1.1\r\n"
5561 "Host: www.example.com\r\n"
5562 "Connection: keep-alive\r\n\r\n");
5563 const MockWrite kGetProxy(
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\r\n");
5567 const MockWrite kGetAuth(
5568 "GET / HTTP/1.1\r\n"
5569 "Host: www.example.com\r\n"
5570 "Connection: keep-alive\r\n"
5571 "Authorization: auth_token\r\n\r\n");
5572 const MockWrite kGetProxyAuth(
5573 "GET http://www.example.com/ HTTP/1.1\r\n"
5574 "Host: www.example.com\r\n"
5575 "Proxy-Connection: keep-alive\r\n"
5576 "Proxy-Authorization: auth_token\r\n\r\n");
5577 const MockWrite kGetAuthThroughProxy(
5578 "GET http://www.example.com/ HTTP/1.1\r\n"
5579 "Host: www.example.com\r\n"
5580 "Proxy-Connection: keep-alive\r\n"
5581 "Authorization: auth_token\r\n\r\n");
5582 const MockWrite kGetAuthWithProxyAuth(
5583 "GET http://www.example.com/ HTTP/1.1\r\n"
5584 "Host: www.example.com\r\n"
5585 "Proxy-Connection: keep-alive\r\n"
5586 "Proxy-Authorization: auth_token\r\n"
5587 "Authorization: auth_token\r\n\r\n");
5588 const MockWrite kConnect(
5589 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5590 "Host: www.example.com\r\n"
5591 "Proxy-Connection: keep-alive\r\n\r\n");
5592 const MockWrite kConnectProxyAuth(
5593 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5594 "Host: www.example.com\r\n"
5595 "Proxy-Connection: keep-alive\r\n"
5596 "Proxy-Authorization: auth_token\r\n\r\n");
5597
5598 const MockRead kSuccess(
5599 "HTTP/1.1 200 OK\r\n"
5600 "Content-Type: text/html; charset=iso-8859-1\r\n"
5601 "Content-Length: 3\r\n\r\n"
5602 "Yes");
5603 const MockRead kFailure(
5604 "Should not be called.");
5605 const MockRead kServerChallenge(
5606 "HTTP/1.1 401 Unauthorized\r\n"
5607 "WWW-Authenticate: Mock realm=server\r\n"
5608 "Content-Type: text/html; charset=iso-8859-1\r\n"
5609 "Content-Length: 14\r\n\r\n"
5610 "Unauthorized\r\n");
5611 const MockRead kProxyChallenge(
5612 "HTTP/1.1 407 Unauthorized\r\n"
5613 "Proxy-Authenticate: Mock realm=proxy\r\n"
5614 "Proxy-Connection: close\r\n"
5615 "Content-Type: text/html; charset=iso-8859-1\r\n"
5616 "Content-Length: 14\r\n\r\n"
5617 "Unauthorized\r\n");
5618 const MockRead kProxyConnected(
5619 "HTTP/1.1 200 Connection Established\r\n\r\n");
5620
5621 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
5622 // no constructors, but the C++ compiler on Windows warns about
5623 // unspecified data in compound literals. So, moved to using constructors,
5624 // and TestRound's created with the default constructor should not be used.
5625 struct TestRound {
5626 TestRound()
5627 : expected_rv(ERR_UNEXPECTED),
5628 extra_write(NULL),
5629 extra_read(NULL) {
5630 }
5631 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5632 int expected_rv_arg)
5633 : write(write_arg),
5634 read(read_arg),
5635 expected_rv(expected_rv_arg),
5636 extra_write(NULL),
5637 extra_read(NULL) {
5638 }
5639 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5640 int expected_rv_arg, const MockWrite* extra_write_arg,
5641 const MockWrite* extra_read_arg)
5642 : write(write_arg),
5643 read(read_arg),
5644 expected_rv(expected_rv_arg),
5645 extra_write(extra_write_arg),
5646 extra_read(extra_read_arg) {
5647 }
5648 MockWrite write;
5649 MockRead read;
5650 int expected_rv;
5651 const MockWrite* extra_write;
5652 const MockRead* extra_read;
5653 };
5654
5655 static const int kNoSSL = 500;
5656
5657 struct TestConfig {
5658 const char* proxy_url;
5659 AuthTiming proxy_auth_timing;
5660 int proxy_auth_rv;
5661 const char* server_url;
5662 AuthTiming server_auth_timing;
5663 int server_auth_rv;
5664 int num_auth_rounds;
5665 int first_ssl_round;
5666 TestRound rounds[3];
5667 } test_configs[] = {
5668 // Non-authenticating HTTP server with a direct connection.
5669 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5670 { TestRound(kGet, kSuccess, OK)}},
5671 // Authenticating HTTP server with a direct connection.
5672 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5673 { TestRound(kGet, kServerChallenge, OK),
5674 TestRound(kGetAuth, kSuccess, OK)}},
5675 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5676 { TestRound(kGet, kServerChallenge, OK),
5677 TestRound(kGetAuth, kFailure, kAuthErr)}},
5678 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5679 { TestRound(kGet, kServerChallenge, OK),
5680 TestRound(kGetAuth, kSuccess, OK)}},
5681 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5682 { TestRound(kGet, kServerChallenge, OK),
5683 TestRound(kGetAuth, kFailure, kAuthErr)}},
5684 // Non-authenticating HTTP server through a non-authenticating proxy.
5685 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5686 { TestRound(kGetProxy, kSuccess, OK)}},
5687 // Authenticating HTTP server through a non-authenticating proxy.
5688 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5689 { TestRound(kGetProxy, kServerChallenge, OK),
5690 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5691 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5692 { TestRound(kGetProxy, kServerChallenge, OK),
5693 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5694 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5695 { TestRound(kGetProxy, kServerChallenge, OK),
5696 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5697 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5698 { TestRound(kGetProxy, kServerChallenge, OK),
5699 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5700 // Non-authenticating HTTP server through an authenticating proxy.
5701 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5702 { TestRound(kGetProxy, kProxyChallenge, OK),
5703 TestRound(kGetProxyAuth, kSuccess, OK)}},
5704 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5705 { TestRound(kGetProxy, kProxyChallenge, OK),
5706 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5707 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5708 { TestRound(kGetProxy, kProxyChallenge, OK),
5709 TestRound(kGetProxyAuth, kSuccess, OK)}},
5710 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5711 { TestRound(kGetProxy, kProxyChallenge, OK),
5712 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5713 // Authenticating HTTP server through an authenticating proxy.
5714 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5715 { TestRound(kGetProxy, kProxyChallenge, OK),
5716 TestRound(kGetProxyAuth, kServerChallenge, OK),
5717 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5718 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5719 { TestRound(kGetProxy, kProxyChallenge, OK),
5720 TestRound(kGetProxyAuth, kServerChallenge, OK),
5721 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5722 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5723 { TestRound(kGetProxy, kProxyChallenge, OK),
5724 TestRound(kGetProxyAuth, kServerChallenge, OK),
5725 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5726 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5727 { TestRound(kGetProxy, kProxyChallenge, OK),
5728 TestRound(kGetProxyAuth, kServerChallenge, OK),
5729 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5730 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5731 { TestRound(kGetProxy, kProxyChallenge, OK),
5732 TestRound(kGetProxyAuth, kServerChallenge, OK),
5733 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5734 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5735 { TestRound(kGetProxy, kProxyChallenge, OK),
5736 TestRound(kGetProxyAuth, kServerChallenge, OK),
5737 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5738 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5739 { TestRound(kGetProxy, kProxyChallenge, OK),
5740 TestRound(kGetProxyAuth, kServerChallenge, OK),
5741 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5742 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5743 { TestRound(kGetProxy, kProxyChallenge, OK),
5744 TestRound(kGetProxyAuth, kServerChallenge, OK),
5745 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5746 // Non-authenticating HTTPS server with a direct connection.
5747 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5748 { TestRound(kGet, kSuccess, OK)}},
5749 // Authenticating HTTPS server with a direct connection.
5750 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5751 { TestRound(kGet, kServerChallenge, OK),
5752 TestRound(kGetAuth, kSuccess, OK)}},
5753 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5754 { TestRound(kGet, kServerChallenge, OK),
5755 TestRound(kGetAuth, kFailure, kAuthErr)}},
5756 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5757 { TestRound(kGet, kServerChallenge, OK),
5758 TestRound(kGetAuth, kSuccess, OK)}},
5759 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5760 { TestRound(kGet, kServerChallenge, OK),
5761 TestRound(kGetAuth, kFailure, kAuthErr)}},
5762 // Non-authenticating HTTPS server with a non-authenticating proxy.
5763 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5764 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
5765 // Authenticating HTTPS server through a non-authenticating proxy.
5766 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5767 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5768 TestRound(kGetAuth, kSuccess, OK)}},
5769 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5770 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5771 TestRound(kGetAuth, kFailure, kAuthErr)}},
5772 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5773 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5774 TestRound(kGetAuth, kSuccess, OK)}},
5775 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5776 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5777 TestRound(kGetAuth, kFailure, kAuthErr)}},
5778 // Non-Authenticating HTTPS server through an authenticating proxy.
5779 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5780 { TestRound(kConnect, kProxyChallenge, OK),
5781 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5782 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5783 { TestRound(kConnect, kProxyChallenge, OK),
5784 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5785 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5786 { TestRound(kConnect, kProxyChallenge, OK),
5787 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5788 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5789 { TestRound(kConnect, kProxyChallenge, OK),
5790 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5791 // Authenticating HTTPS server through an authenticating proxy.
5792 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5793 { TestRound(kConnect, kProxyChallenge, OK),
5794 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5795 &kGet, &kServerChallenge),
5796 TestRound(kGetAuth, kSuccess, OK)}},
5797 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5798 { TestRound(kConnect, kProxyChallenge, OK),
5799 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5800 &kGet, &kServerChallenge),
5801 TestRound(kGetAuth, kFailure, kAuthErr)}},
5802 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5803 { TestRound(kConnect, kProxyChallenge, OK),
5804 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5805 &kGet, &kServerChallenge),
5806 TestRound(kGetAuth, kSuccess, OK)}},
5807 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5808 { TestRound(kConnect, kProxyChallenge, OK),
5809 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5810 &kGet, &kServerChallenge),
5811 TestRound(kGetAuth, kFailure, kAuthErr)}},
5812 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5813 { TestRound(kConnect, kProxyChallenge, OK),
5814 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5815 &kGet, &kServerChallenge),
5816 TestRound(kGetAuth, kSuccess, OK)}},
5817 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5818 { TestRound(kConnect, kProxyChallenge, OK),
5819 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5820 &kGet, &kServerChallenge),
5821 TestRound(kGetAuth, kFailure, kAuthErr)}},
5822 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5823 { TestRound(kConnect, kProxyChallenge, OK),
5824 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5825 &kGet, &kServerChallenge),
5826 TestRound(kGetAuth, kSuccess, OK)}},
5827 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5828 { TestRound(kConnect, kProxyChallenge, OK),
5829 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5830 &kGet, &kServerChallenge),
5831 TestRound(kGetAuth, kFailure, kAuthErr)}},
5832 };
5833
5834 SessionDependencies session_deps;
5835 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]3fd9dae2010-06-21 11:39:005836 HttpAuthHandlerMock::Factory* auth_factory(
5837 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:155838 session_deps.http_auth_handler_factory.reset(auth_factory);
5839
5840 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
5841 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:265842
5843 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:155844 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005845 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155846 std::string auth_challenge = "Mock realm=proxy";
5847 GURL origin(test_config.proxy_url);
5848 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5849 auth_challenge.end());
5850 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
5851 origin, BoundNetLog());
5852 auth_handler->SetGenerateExpectation(
5853 test_config.proxy_auth_timing == AUTH_ASYNC,
5854 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:155855 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
5856 }
5857 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005858 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155859 std::string auth_challenge = "Mock realm=server";
5860 GURL origin(test_config.server_url);
5861 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5862 auth_challenge.end());
5863 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
5864 origin, BoundNetLog());
5865 auth_handler->SetGenerateExpectation(
5866 test_config.server_auth_timing == AUTH_ASYNC,
5867 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:155868 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
5869 }
5870 if (test_config.proxy_url) {
5871 session_deps.proxy_service =
5872 CreateFixedProxyService(test_config.proxy_url);
5873 } else {
5874 session_deps.proxy_service = ProxyService::CreateNull();
5875 }
5876
5877 HttpRequestInfo request;
5878 request.method = "GET";
5879 request.url = GURL(test_config.server_url);
5880 request.load_flags = 0;
5881
5882 scoped_ptr<HttpTransaction> trans(
5883 new HttpNetworkTransaction(CreateSession(&session_deps)));
5884
5885 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
5886 const TestRound& read_write_round = test_config.rounds[round];
5887
5888 // Set up expected reads and writes.
5889 MockRead reads[2];
5890 reads[0] = read_write_round.read;
5891 size_t length_reads = 1;
5892 if (read_write_round.extra_read) {
5893 reads[1] = *read_write_round.extra_read;
5894 length_reads = 2;
5895 }
5896
5897 MockWrite writes[2];
5898 writes[0] = read_write_round.write;
5899 size_t length_writes = 1;
5900 if (read_write_round.extra_write) {
5901 writes[1] = *read_write_round.extra_write;
5902 length_writes = 2;
5903 }
5904 StaticSocketDataProvider data_provider(
5905 reads, length_reads, writes, length_writes);
5906 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
5907
5908 // Add an SSL sequence if necessary.
5909 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
5910 if (round >= test_config.first_ssl_round)
5911 session_deps.socket_factory.AddSSLSocketDataProvider(
5912 &ssl_socket_data_provider);
5913
5914 // Start or restart the transaction.
5915 TestCompletionCallback callback;
5916 int rv;
5917 if (round == 0) {
5918 rv = trans->Start(&request, &callback, BoundNetLog());
5919 } else {
[email protected]13c8a092010-07-29 06:15:445920 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:155921 }
5922 if (rv == ERR_IO_PENDING)
5923 rv = callback.WaitForResult();
5924
5925 // Compare results with expected data.
5926 EXPECT_EQ(read_write_round.expected_rv, rv);
5927 const HttpResponseInfo* response = trans->GetResponseInfo();
5928 if (read_write_round.expected_rv == OK) {
5929 EXPECT_FALSE(response == NULL);
5930 } else {
5931 EXPECT_TRUE(response == NULL);
5932 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
5933 continue;
5934 }
5935 if (round + 1 < test_config.num_auth_rounds) {
5936 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5937 } else {
5938 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5939 }
5940 }
[email protected]e5ae96a2010-04-14 20:12:455941 }
[email protected]e60e47a2010-07-14 03:37:185942
5943 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
5944 session->FlushSocketPools();
[email protected]e5ae96a2010-04-14 20:12:455945}
5946
[email protected]c871bce92010-07-15 21:51:145947TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
5948 // Do multi-round authentication and make sure it works correctly.
5949 SessionDependencies session_deps;
5950 HttpAuthHandlerMock::Factory* auth_factory(
5951 new HttpAuthHandlerMock::Factory());
5952 session_deps.http_auth_handler_factory.reset(auth_factory);
5953 session_deps.proxy_service = ProxyService::CreateNull();
5954 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
5955 session_deps.host_resolver->set_synchronous_mode(true);
5956
5957 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
5958 auth_handler->set_connection_based(true);
5959 std::string auth_challenge = "Mock realm=server";
5960 GURL origin("http://www.example.com");
5961 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5962 auth_challenge.end());
5963 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
5964 origin, BoundNetLog());
5965 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
5966
5967 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
5968 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5969
5970 int rv = OK;
5971 const HttpResponseInfo* response = NULL;
5972 HttpRequestInfo request;
5973 request.method = "GET";
5974 request.url = origin;
5975 request.load_flags = 0;
5976 TestCompletionCallback callback;
5977
5978 const MockWrite kGet(
5979 "GET / HTTP/1.1\r\n"
5980 "Host: www.example.com\r\n"
5981 "Connection: keep-alive\r\n\r\n");
5982 const MockWrite kGetAuth(
5983 "GET / HTTP/1.1\r\n"
5984 "Host: www.example.com\r\n"
5985 "Connection: keep-alive\r\n"
5986 "Authorization: auth_token\r\n\r\n");
5987
5988 const MockRead kServerChallenge(
5989 "HTTP/1.1 401 Unauthorized\r\n"
5990 "WWW-Authenticate: Mock realm=server\r\n"
5991 "Content-Type: text/html; charset=iso-8859-1\r\n"
5992 "Content-Length: 14\r\n\r\n"
5993 "Unauthorized\r\n");
5994 const MockRead kSuccess(
5995 "HTTP/1.1 200 OK\r\n"
5996 "Content-Type: text/html; charset=iso-8859-1\r\n"
5997 "Content-Length: 3\r\n\r\n"
5998 "Yes");
5999
6000 MockWrite writes[] = {
6001 // First round
6002 kGet,
6003 // Second round
6004 kGetAuth,
6005 // Third round
6006 kGetAuth,
6007 };
6008 MockRead reads[] = {
6009 // First round
6010 kServerChallenge,
6011 // Second round
6012 kServerChallenge,
6013 // Third round
6014 kSuccess,
6015 };
6016 StaticSocketDataProvider data_provider(reads, arraysize(reads),
6017 writes, arraysize(writes));
6018 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6019
6020 // First round
6021 auth_handler->SetGenerateExpectation(false, OK);
6022 rv = trans->Start(&request, &callback, BoundNetLog());
6023 if (rv == ERR_IO_PENDING)
6024 rv = callback.WaitForResult();
6025 EXPECT_EQ(OK, rv);
6026 response = trans->GetResponseInfo();
6027 ASSERT_FALSE(response == NULL);
6028 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6029
6030 // Second round
6031 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446032 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:146033 if (rv == ERR_IO_PENDING)
6034 rv = callback.WaitForResult();
6035 EXPECT_EQ(OK, rv);
6036 response = trans->GetResponseInfo();
6037 ASSERT_FALSE(response == NULL);
6038 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6039
6040 // Third round
6041 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446042 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:146043 if (rv == ERR_IO_PENDING)
6044 rv = callback.WaitForResult();
6045 EXPECT_EQ(OK, rv);
6046 response = trans->GetResponseInfo();
6047 ASSERT_FALSE(response == NULL);
6048 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6049}
6050
[email protected]aeaca1f2010-04-20 22:05:216051class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
6052 public:
[email protected]06650c52010-06-03 00:49:176053 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:216054 : fail_all_(fail_all) {
6055 }
6056
6057 virtual MockRead GetNextRead() {
6058 if (fail_all_)
6059 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
6060
6061 return MockRead(false /* async */,
6062 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
6063 }
6064
6065 virtual MockWriteResult OnWrite(const std::string& data) {
6066 return MockWriteResult(false /* async */, data.size());
6067 }
6068
6069 void Reset() {
6070 }
6071
6072 private:
6073 const bool fail_all_;
6074};
6075
6076// Test that we restart a connection when we see a decompression failure from
6077// the peer during the handshake. (In the real world we'll restart with SSLv3
6078// and we won't offer DEFLATE in that case.)
6079TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
6080 HttpRequestInfo request;
6081 request.method = "GET";
6082 request.url = GURL("https://tlsdecompressionfailure.example.com/");
6083 request.load_flags = 0;
6084
6085 SessionDependencies session_deps;
6086 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6087 false /* fail all reads */);
6088 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6089 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:116090 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:216091 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6092 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6093 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6094 session_deps.socket_factory.AddSSLSocketDataProvider(
6095 &ssl_socket_data_provider1);
6096 session_deps.socket_factory.AddSSLSocketDataProvider(
6097 &ssl_socket_data_provider2);
6098
[email protected]e60e47a2010-07-14 03:37:186099 // Work around http://crbug.com/37454
6100 StaticSocketDataProvider bug37454_connection;
6101 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
6102 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
6103
[email protected]aeaca1f2010-04-20 22:05:216104 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6105 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6106 TestCompletionCallback callback;
6107
[email protected]5a1d7ca2010-04-28 20:12:276108 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216109 EXPECT_EQ(ERR_IO_PENDING, rv);
6110 EXPECT_EQ(OK, callback.WaitForResult());
6111
6112 const HttpResponseInfo* response = trans->GetResponseInfo();
6113 ASSERT_TRUE(response != NULL);
6114 ASSERT_TRUE(response->headers != NULL);
6115 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6116
6117 std::string response_data;
6118 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6119 EXPECT_EQ("ok.", response_data);
6120}
6121
6122// Test that we restart a connection if we get a decompression failure from the
6123// peer while reading the first bytes from the connection. This occurs when the
6124// peer cannot handle DEFLATE but we're using False Start, so we don't notice
6125// in the handshake.
6126TEST_F(HttpNetworkTransactionTest,
6127 RestartAfterTLSDecompressionFailureWithFalseStart) {
6128 HttpRequestInfo request;
6129 request.method = "GET";
6130 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
6131 request.load_flags = 0;
6132
6133 SessionDependencies session_deps;
6134 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6135 true /* fail all reads */);
6136 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6137 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
6138 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6139 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6140 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6141 session_deps.socket_factory.AddSSLSocketDataProvider(
6142 &ssl_socket_data_provider1);
6143 session_deps.socket_factory.AddSSLSocketDataProvider(
6144 &ssl_socket_data_provider2);
6145
6146 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6147 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6148 TestCompletionCallback callback;
6149
[email protected]5a1d7ca2010-04-28 20:12:276150 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216151 EXPECT_EQ(ERR_IO_PENDING, rv);
6152 EXPECT_EQ(OK, callback.WaitForResult());
6153
6154 const HttpResponseInfo* response = trans->GetResponseInfo();
6155 ASSERT_TRUE(response != NULL);
6156 ASSERT_TRUE(response->headers != NULL);
6157 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6158
6159 std::string response_data;
6160 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6161 EXPECT_EQ("ok.", response_data);
6162}
6163
[email protected]65041fa2010-05-21 06:56:536164// This tests the case that a request is issued via http instead of spdy after
6165// npn is negotiated.
6166TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
6167 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6168 HttpNetworkTransaction::SetNextProtos("\x08http/1.1\x07http1.1");
6169 SessionDependencies session_deps;
6170 HttpRequestInfo request;
6171 request.method = "GET";
6172 request.url = GURL("https://www.google.com/");
6173 request.load_flags = 0;
6174
6175 MockWrite data_writes[] = {
6176 MockWrite("GET / HTTP/1.1\r\n"
6177 "Host: www.google.com\r\n"
6178 "Connection: keep-alive\r\n\r\n"),
6179 };
6180
6181 MockRead data_reads[] = {
6182 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356183 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:536184 MockRead("hello world"),
6185 MockRead(false, OK),
6186 };
6187
6188 SSLSocketDataProvider ssl(true, OK);
6189 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6190 ssl.next_proto = "http/1.1";
6191
6192 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6193
6194 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6195 data_writes, arraysize(data_writes));
6196 session_deps.socket_factory.AddSocketDataProvider(&data);
6197
6198 TestCompletionCallback callback;
6199
6200 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6201 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6202
6203 int rv = trans->Start(&request, &callback, BoundNetLog());
6204
6205 EXPECT_EQ(ERR_IO_PENDING, rv);
6206 EXPECT_EQ(OK, callback.WaitForResult());
6207
6208 const HttpResponseInfo* response = trans->GetResponseInfo();
6209 ASSERT_TRUE(response != NULL);
6210 ASSERT_TRUE(response->headers != NULL);
6211 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6212
6213 std::string response_data;
6214 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6215 EXPECT_EQ("hello world", response_data);
6216
6217 EXPECT_FALSE(response->was_fetched_via_spdy);
6218 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576219 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:536220
6221 HttpNetworkTransaction::SetNextProtos("");
6222 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6223}
[email protected]26ef6582010-06-24 02:30:476224
6225TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
6226 // Simulate the SSL handshake completing with an NPN negotiation
6227 // followed by an immediate server closing of the socket.
6228 // Fix crash: http://crbug.com/46369
6229 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:356230 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:476231 SessionDependencies session_deps;
6232
6233 HttpRequestInfo request;
6234 request.method = "GET";
6235 request.url = GURL("https://www.google.com/");
6236 request.load_flags = 0;
6237
6238 SSLSocketDataProvider ssl(true, OK);
6239 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356240 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:476241 ssl.was_npn_negotiated = true;
6242 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6243
[email protected]2bd93022010-07-17 00:58:446244 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136245 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:476246
6247 MockRead spdy_reads[] = {
6248 MockRead(false, 0, 0) // Not async - return 0 immediately.
6249 };
6250
6251 scoped_refptr<DelayedSocketData> spdy_data(
6252 new DelayedSocketData(
6253 0, // don't wait in this case, immediate hangup.
6254 spdy_reads, arraysize(spdy_reads),
6255 spdy_writes, arraysize(spdy_writes)));
6256 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6257
6258 TestCompletionCallback callback;
6259
6260 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6261 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6262
6263 int rv = trans->Start(&request, &callback, BoundNetLog());
6264 EXPECT_EQ(ERR_IO_PENDING, rv);
6265 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
6266
6267 HttpNetworkTransaction::SetNextProtos("");
6268 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6269}
[email protected]65d34382010-07-01 18:12:266270
[email protected]f45c1ee2010-08-03 00:54:306271TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
6272 // This test ensures that the URL passed into the proxy is upgraded
6273 // to https when doing an Alternate Protocol upgrade.
6274 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6275 HttpNetworkTransaction::SetNextProtos(
6276 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
6277
6278 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
6279 HttpAuthHandlerMock::Factory* auth_factory =
6280 new HttpAuthHandlerMock::Factory();
6281 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
6282 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6283 auth_factory->set_do_init_from_challenge(true);
6284 session_deps.http_auth_handler_factory.reset(auth_factory);
6285
6286 HttpRequestInfo request;
6287 request.method = "GET";
6288 request.url = GURL("http://www.google.com");
6289 request.load_flags = 0;
6290
6291 // First round goes unauthenticated through the proxy.
6292 MockWrite data_writes_1[] = {
6293 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
6294 "Host: www.google.com\r\n"
6295 "Proxy-Connection: keep-alive\r\n"
6296 "\r\n"),
6297 };
6298 MockRead data_reads_1[] = {
6299 MockRead("HTTP/1.1 200 OK\r\n"
6300 "Alternate-Protocol: 443:npn-spdy/2\r\n"
6301 "Proxy-Connection: close\r\n"
6302 "\r\n"),
6303 };
6304 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
6305 data_writes_1, arraysize(data_writes_1));
6306
6307 // Second round tries to tunnel to www.google.com due to the
6308 // Alternate-Protocol announcement in the first round. It fails due
6309 // to a proxy authentication challenge.
6310 MockWrite data_writes_2[] = {
6311 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6312 "Host: www.google.com\r\n"
6313 "Proxy-Connection: keep-alive\r\n"
6314 "\r\n"),
6315 };
6316 MockRead data_reads_2[] = {
6317 MockRead("HTTP/1.0 407 Unauthorized\r\n"
6318 "Proxy-Authenticate: Mock\r\n"
6319 "Proxy-Connection: close\r\n"
6320 "\r\n"),
6321 };
6322 StaticSocketDataProvider data_2(data_reads_2, arraysize(data_reads_2),
6323 data_writes_2, arraysize(data_writes_2));
6324
6325 // Third round establishes a tunnel to www.google.com due to the
6326 // Alternate-Protocol announcement in the first round, and does a SPDY
6327 // request round.
6328 // TODO(cbentzel): Originally, this just returned another 407 so the unit test
6329 // could skip the SSL connection establishment and SPDY framing issues. Alas,
6330 // the retry-http-when-alternate-protocol fails logic kicks in, which was more
6331 // complicated to set up expectations for than the SPDY session.
6332 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6333 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6334 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
6335
6336 MockWrite data_writes_3[] = {
6337 // TUNNEL connection established
6338 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6339 "Host: www.google.com\r\n"
6340 "Proxy-Connection: keep-alive\r\n"
6341 "Proxy-Authorization: auth_token\r\n"
6342 "\r\n"),
6343 // SPDY request
6344 CreateMockWrite(*req), // 3
6345 };
6346
6347 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6348 MockRead data_reads_3[] = {
6349 // Proxy response
6350 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1),
6351 // SPDY response.
6352 CreateMockRead(*resp.get(), 4),
6353 CreateMockRead(*data.get(), 4),
6354 MockRead(true, 0, 0, 4),
6355 };
6356 scoped_refptr<OrderedSocketData> data_3(
6357 new OrderedSocketData(data_reads_3, arraysize(data_reads_3),
6358 data_writes_3, arraysize(data_writes_3)));
6359
6360 SSLSocketDataProvider ssl(true, OK);
6361 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6362 ssl.next_proto = "spdy/2";
6363 ssl.was_npn_negotiated = true;
6364
6365 session_deps.socket_factory.AddSocketDataProvider(&data_1);
6366 session_deps.socket_factory.AddSocketDataProvider(&data_2);
6367 session_deps.socket_factory.AddSocketDataProvider(data_3.get());
6368 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6369 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6370
6371 // First round should work and provide the Alternate-Protocol state.
6372 TestCompletionCallback callback_1;
6373 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
6374 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
6375 EXPECT_EQ(ERR_IO_PENDING, rv);
6376 EXPECT_EQ(OK, callback_1.WaitForResult());
6377
6378 // Second round should attempt a tunnel connect and get an auth challenge.
6379 TestCompletionCallback callback_2;
6380 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
6381 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
6382 EXPECT_EQ(ERR_IO_PENDING, rv);
6383 EXPECT_EQ(OK, callback_2.WaitForResult());
6384 const HttpResponseInfo* response = trans_2->GetResponseInfo();
6385 ASSERT_FALSE(response == NULL);
6386 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6387
6388 // Restart with auth. Tunnel should work and response received.
6389 TestCompletionCallback callback_3;
6390 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
6391 EXPECT_EQ(ERR_IO_PENDING, rv);
6392 EXPECT_EQ(OK, callback_3.WaitForResult());
6393
6394 // After all that work, these two lines (or actually, just the scheme) are
6395 // what this test is all about. Make sure it happens correctly.
6396 const GURL& request_url = auth_handler->request_url();
6397 EXPECT_EQ("https", request_url.scheme());
6398 EXPECT_EQ("www.google.com", request_url.host());
6399
6400 HttpNetworkTransaction::SetNextProtos("");
6401 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6402}
6403
[email protected]89ceba9a2009-03-21 03:46:066404} // namespace net